pandas如何压缩列中的列表,同时保持每个元素的列表ID

时间:2018-03-30 13:38:24

标签: python-3.x pandas dataframe

我有以下df

 A                                                          id
[ObjectId('5abb6fab81c0')]                                  0
[ObjectId('5abb6fab81c3'),ObjectId('5abb6fab81c4')]         1
[ObjectId('5abb6fab81c2'),ObjectId('5abb6fab81c1')]         2

我想在A中展平每个列表,并将相应的id分配给列表中的每个元素,例如

 A                               id
 ObjectId('5abb6fab81c0')        0
 ObjectId('5abb6fab81c3')        1
 ObjectId('5abb6fab81c4')        1
 ObjectId('5abb6fab81c2')        2
 ObjectId('5abb6fab81c1')        2

3 个答案:

答案 0 :(得分:2)

这可能不是最优雅的解决方案,但它确实有效。这里的想法是循环遍历df(这就是为什么这可能是一个低效的解决方案),然后遍历列A中的每个列表,将每个项目和id附加到新的名单。然后将这两个新列表转换为新的DataFrame。

a_list = []
id_list = []
for index, a, i in df.itertuples():
    for item in a:
        a_list.append(item)
        id_list.append(i)
df1 = pd.DataFrame(list(zip(alist, idlist)), columns=['A', 'id'])

正如我所说,不优雅,但它完成了工作。可能至少有一种更好的方法来优化它,但希望它能让你前进。

编辑(2018年4月2日)

我想到了我的和温的代码之间的时间比较,只是出于好奇。这两个变量是列A的长度,以及列A中列表条目的长度。我运行了一堆测试用例,每次迭代数量级。例如,我从A长度= 10开始,并在每个步骤中迭代通过随机化的A条目列表长度1-10,1-100 ... 1-1,000,000来运行到1,000,000。我找到了以下内容:

  • 总的来说,只要列表长度小于〜1,000,我的代码就会明显更快(尤其<增加A个长度)。随机列表长度达到~1,000的障碍,Wen的代码接管速度。这对我来说是一个巨大的惊喜!我完全希望我的代码每次都丢失。
  • A的长度通常无关紧要 - 它只是线性增加整体执行时间。它改变结果的唯一情况是A长度= 10.在这种情况下,无论列表长度如何,我的代码运行得更快(对我来说也很奇怪)。

结论:如果A中的列表条目长度为几百个元素(或更少),我的代码就可以了。但是,如果您正在使用大量数据集,请使用Wen的!另外值得注意的是,当你达到1,000,000的障碍时,两种方法都会大幅减速。我正在使用一台功能相当强大的计算机,每台计算机都要花费几分钟时间(它实际上在A长度= 1,000,000,列表长度= 1,000,000的情况下崩溃)。

答案 1 :(得分:2)

我认为评论来自这个问题?你可以使用我的original post或者这个

df.set_index('id').A.apply(pd.Series).stack().reset_index().drop('level_1',1)
Out[497]: 
   id    0
0   0  1.0
1   1  2.0
2   1  3.0
3   1  4.0
4   2  5.0
5   2  6.0

pd.DataFrame({'id':df.id.repeat(df.A.str.len()),'A':df.A.sum()})
Out[498]: 
   A  id
0  1   0
1  2   1
1  3   1
1  4   1
2  5   2
2  6   2

答案 2 :(得分:0)

可以使用此功能进行平整和不平整

def flatten(df, col):
    col_flat = pd.DataFrame([[i, x] for i, y in df[col].apply(list).iteritems() for x in y], columns=['I', col])
    col_flat = col_flat.set_index('I')
    df = df.drop(col, 1)
    df = df.merge(col_flat, left_index=True, right_index=True)

    return df

展平:

def unflatten(flat_df, col):
    flat_df.groupby(level=0).agg({**{c:'first' for c in flat_df.columns}, col: list})

展开后,除了列顺序外,我们得到相同的数据框:

(df.sort_index(axis=1) == unflatten(flatten(df)).sort_index(axis=1)).all().all()
>> True

要创建唯一索引,可以在展平后调用reset_index