Pandas分组依据和加入列表

ctehm74n  于 2022-12-02  发布在  其他
关注(0)|答案(6)|浏览(125)

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

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转换为list。我该如何做?
  • 在df.groupby(...).中的函数应用什么(λ x:...)适用于?x?list的形式是什么?
  • 我主要问题的解决方案

先谢谢你。

ejk8hzay

ejk8hzay1#

object dtype是一个包罗万象的dtype,基本上不表示int、float、bool、datetime或timedelta。因此它将它们存储为列表。convert_objects尝试将列转换为这些dtype之一。
你要

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]

eufgjt7s

eufgjt7s2#

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

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

z6psavjg

z6psavjg3#

上面提出的使用df.groupby('column_a').agg(sum)的方法确实有效。但是,你必须确保你的列表只包含integers,否则输出将不一样。
如果要将所有列表项转换为整数,可以用途:

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

hpxqektj4#

accepted answer建议使用groupby.sum,它可以很好地处理少量列表,但是使用sum来连接列表是二次
对于大量列表,一个快得多的选项是使用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])
      )

输出:

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)

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

wgx48brx5#

使用麻木而简单的“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倍。

nbysray5

nbysray56#

谢谢,帮了我的忙

相关问题