繁体   English   中英

pandas groupby 和加入列表

[英]pandas groupby and join lists

我有一个 dataframe df,有两列,我想按一列分组并加入属于同一组的列表,例如:

column_a, column_b
1,         [1,2,3]
1,         [2,5]
2,         [5,6]

处理后:

column_a, column_b
1,         [1,2,3,2,5]
2,         [5,6]

我想保留所有重复项。 我有以下问题:

  • dataframe 的数据类型是对象。 convert_objects() 不会自动将 column_b 转换为列表。 我怎样才能做到这一点?
  • df.groupby(...).apply(lambda x: ...) 中的 function 适用于什么? x的形式是什么? 列表?
  • 我的主要问题的解决方案?

提前致谢。

object dtype 是一个包罗万象的 dtype,基本上意味着不是 int、float、bool、datetime 或 timedelta。 所以它将它们存储为一个列表。 convert_objects尝试将一列转换为这些数据类型之一。

你要

In [63]: df
Out[63]: 
   a          b    c
0  1  [1, 2, 3]  foo
1  1     [2, 5]  bar
2  2     [5, 6]  baz


In [64]: df.groupby('a').agg({'b': 'sum', 'c': lambda x: ' '.join(x)})
Out[64]: 
         c                b
a                          
1  foo bar  [1, 2, 3, 2, 5]
2      baz           [5, 6]

这将按a列中的值对数据框进行分组。 阅读更多关于groupby 的信息

这是做一个常规的列表sum (串联)就像[1, 2, 3] + [2, 5]与结果[1, 2, 3, 2, 5]

df.groupby('column_a').agg(sum)

这是有效的,因为运算符重载sum将列表连接在一起。 结果 df 的索引将是column_a的值:

使用 numpy 和简单的“for”或“map”:

import numpy as np

u_clm = np.unique(df.column_a.values)
all_lists = []

for clm in u_clm:
    df_process = df.query('column_a == @clm')
    list_ = np.concatenate(df.column_b.values)
    all_lists.append((clm, list_.tolist()))

df_sum_lists = pd.DataFrame(all_lists)

对于大型数据集,它比简单的“groupby-agg-sum”方法快 350 倍。

上面提出的使用df.groupby('column_a').agg(sum)的方法df.groupby('column_a').agg(sum)有效。 但是,您必须确保您的列表仅包含integers ,否则输出将不同。

如果要将所有列表项转换为整数,可以使用:

df['column_a'] = df['column_a'].apply(lambda x: list(map(int, x)))

接受的答案建议使用groupby.sum ,它适用于少量列表,但是使用 sum 连接列表是quadratic

对于大量列表,更快的选择是使用itertools.chain或列表推导:

df = pd.DataFrame({'column_a': ['1', '1', '2'],
                   'column_b': [['1', '2', '3'], ['2', '5'], ['5', '6']]})

itertools.chain

from itertools import chain
out = (df.groupby('column_a', as_index=False)['column_b']
         .agg(lambda x: list(chain.from_iterable(x)))
       )

列表理解:

out = (df.groupby('column_a', as_index=False, sort=False)['column_b']
         .agg(lambda x: [e for l in x for e in l])
      )

output:

  column_a         column_b
0        1  [1, 2, 3, 2, 5]
1        2           [5, 6]

速度比较

使用示例的 n 次重复来显示要合并的列表数量的影响:

test_df = pd.concat([df]*n, ignore_index=True)

比较 pandas 列表合并 groupby

注意。 还比较了方法( agg(lambda x: np.concatenate(x.to_numpy()).tolist()) )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM