元组列表转换成二进制表格?

8

我有一个Python事务/元组列表,其中元素数量不同,例如:

lst = [('apple','banana','carrots'),('apple',),('banana','carrots',)]

我希望将此列表以表格形式存储(最好使用 pd.DataFrame),如下所示:
   apple  banana  carrots
0      1       1        1
1      1       0        0
2      0       1        1

但是如果直接使用pd.DataFrame进行转换,我会得到以下结果:

pd.DataFrame(lst)

        0        1        2
0   apple   banana  carrots
1   apple     None     None
2  banana  carrots     None

如何将这种类型的列表转换为二进制表格?
7个回答

10

如果您在列上使用value_counts,那么这就非常简单了。

pd.DataFrame(lst).apply(pd.value_counts,1).fillna(0)

    apple  banana  carrots
0    1.0     1.0      1.0
1    1.0     0.0      0.0
2    0.0     1.0      1.0

value_counts 似乎是属于你的 :-) - BENY
哈哈,也许吧,感觉用起来不错。 - Bharath M Shetty
嗨@Dark。谢谢你的解决方案。看起来很简单,但是运行起来太慢了。我的列表实际上有超过400万个元素。出于某种原因,Robbie的解决方案运行得更快。你能帮我理解一下为什么吗?谢谢。 - Adriano Arantes
@AdrianoArantes 这就是使用 apply 的缺点,看看 coldspeed 的回答,我认为速度无法超越。 - Bharath M Shetty

7

以下方法:

  1. 定义 lst

  2. 查找 lst 中的所有唯一字符串

  3. 计算列表中每个元组中的出现次数

  4. 创建数据框

在这里实现:

import pandas as pd
import numpy as np

lst = [('apple','banana','carrots'),('apple',),('banana','carrots',)]
cols = np.unique(sum(tuple(lst),()))
data = [[i.count(j) for j in cols] for i in lst]
df = pd.DataFrame(columns=cols, data=data)

输出:

   apple  banana  carrots
0      1       1        1
1      1       0        0
2      0       1        1

如果一行中出现了重复的单个元素,则此内容不会是二进制的。 - Nate
@Nate 是的,没错,如果输入格式与问题中的格式相同,那么它将是二进制的。 - Robbie
谢谢@Robbie,你的解决方案在我的情况下很有效,是的,对于我的问题,每个元素在每行中只出现一次。 - Adriano Arantes
@AdrianoArantes 计数只是 pandas 中的 value_counts,你觉得我的解决方案怎么样? - Bharath M Shetty

7

让我们尝试使用 get_dummies + groupby + sum -

pd.get_dummies(pd.DataFrame(lst)).groupby(by=lambda x: x.split('_')[1], axis=1).sum()

   apple  banana  carrots
0      1       1        1
1      1       0        0
2      0       1        1

这应该非常快。


1
不仅快得漂亮,而且超级快 - Bharath M Shetty
真的非常快!我只用了50秒就处理完了450万个元素的列表!谢谢COLDSPEED!! - Adriano Arantes
@AdrianoArantes 不客气!之前被接受的答案花了多长时间? - cs95
@cᴏʟᴅsᴘᴇᴇᴅ,Robbie的解决方案需要1分30秒。 - Adriano Arantes

3

只需要使用 stackget_dummies 函数

pd.DataFrame(lst).stack().str.get_dummies().sum(level=0)
Out[114]: 
   apple  banana  carrots
0      1       1        1
1      1       0        0
2      0       1        1

你可以的时候看看我的回答! - cs95
1
@cᴏʟᴅsᴘᴇᴇᴅ 很好地使用了 groupby !! - BENY

0

你可以尝试这个:

import itertools
class Table:
   def __init__(self, data):
      self.lst = data
      self.headers = headers = list(set(itertools.chain(*self.lst)))
      self.new_count = {i:[b.count(i) for b in self.lst] for i in self.headers}
   def __getitem__(self, row):
       if isinstance(row, int):
           return [d[row] for c, d in sorted(self.new_count.items(), key=lambda x:x[0])]
       return self.new_count[row]
   def __repr__(self):
       return ' '.join(sorted(self.new_count.keys()))+'\n'+'\n'.join('{}. {}'.format(i, ' '.join(map(str, d))) for i, d in enumerate(zip(*[e[-1] for e in sorted(self.new_count.items(), key=lambda x:x[0])])))

lst = [('apple','banana','carrots'),('apple',),('banana','carrots',)]
t = Table(lst)
print(t)

输出:

apple banana carrots
0. 1 1 1
1. 1 0 0
2. 0 1 1

0

创建一个临时列表,其中的项目转换为二进制,然后使用Dataframe。编写一个循环,将每个项目转换为二进制。

def pad_collection(collection, pad_value):
    sorted_collection = sorted(collection, key=lambda tup: len(tup))
    max_length = len(sorted_collection[-1])
    for item in collection:
        for i in range (max_length - len(item)):
            item.append(pad_value)
    return collection

def convert_to_binary(collection):
    result = []
    padded_collection = pad_collection(collection)
    for i in padded_collection:
        temp = []
        for element in i:
            new_element = int(bool(element))
            temp.append(new_element)
        result.append(tuple(temp))
    return padded_collection

0

你可以尝试使用纯逻辑而不导入任何外部模块,

lst = [('apple','banana','carrots'),('apple',),('banana','carrots',)]

track_uniqu=[]
for i in lst:
    for k in i:

        if k not in track_uniqu:
            track_uniqu.append(k)

final={}
for i,j in enumerate(lst):

    dummy=[0]*len(track_uniqu)

    for k in j:
        if k in track_uniqu:

            dummy[track_uniqu.index(k)]=1
            final[i]=dummy
        else:
            pass
print(final)

输出:

{0: [1, 1, 1], 1: [1, 0, 0], 2: [0, 1, 1]}

结果以字典格式返回,但您可以根据需要将此字典创建为表格数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接