使用作为条目的numpy数组对pandas数据框进行分组和减少。

4

我有一个以下结构的 pandas.DataFrame

>>> data 
a    b    values
1    0    [1, 2, 3, 4]
2    0    [3, 4, 5, 6]
1    1    [1, 3, 7, 9]
2    1    [2, 4, 6, 8]

('values' 的类型是 numpy.array)。我想要做的是按列 'a' 对数据进行分组,然后将值列表组合起来。 我的目标是最终得到以下结果:

>>> data 
a    values
1    [1, 2, 3, 4, 1, 3, 7, 9]
2    [3, 4, 5, 6, 2, 4, 6, 8]

请注意,值的顺序并不重要。我该如何实现这一点?我考虑了一些方法,比如:

>>> grps = data.groupby(['a'])
>>> grps['values'].agg(np.concatenate)

但这会导致 KeyError。我相信有一种pandaic的方式可以实现这个 - 但是怎么做呢?谢谢。

2个回答

3

与John Galt的答案类似,您可以进行分组,然后应用np.hstack

In [278]: df.groupby('a')['values'].apply(np.hstack)
Out[278]: 
a
1    [1, 2, 3, 4, 1, 3, 7, 9]
2    [3, 4, 5, 6, 2, 4, 6, 8]
Name: values, dtype: object 

为了恢复你的数据框,你需要使用pd.Series.to_framepd.reset_index函数:
In [311]: df.groupby('a')['values'].apply(np.hstack).to_frame().reset_index()
Out[311]: 
   a                    values
0  1  [1, 2, 3, 4, 1, 3, 7, 9]
1  2  [3, 4, 5, 6, 2, 4, 6, 8]

性能

df_test = pd.concat([df] * 10000) # setup

%timeit df_test.groupby('a')['values'].apply(np.hstack) # mine
1 loop, best of 3: 219 ms per loop

%timeit df_test.groupby('a')['values'].sum() # John's 
1 loop, best of 3: 4.44 s per loop

sum对于列表非常低效,并且在Valuesnp.array时不起作用。


我该如何实现,使得结果列仍然具有名称“'values'”? - rammelmueller
@rammelmuller 你想怎么处理a和b?放弃它吗? - cs95
默认情况下会删除'b',而'a'应该保留并保持不变。 - rammelmueller
1
@rammelmuller,给你了,享受吧。 - cs95

1
你可以使用 sum 来连接列表。
In [640]: data.groupby('a')['values'].sum()
Out[640]:
a
1    [1, 2, 3, 4, 1, 3, 7, 9]
2    [3, 4, 5, 6, 2, 4, 6, 8]
Name: values, dtype: object

或者,
In [653]: data.groupby('a', as_index=False).agg({'values': 'sum'})
Out[653]:
   a                    values
0  1  [1, 2, 3, 4, 1, 3, 7, 9]
1  2  [3, 4, 5, 6, 2, 4, 6, 8]

似乎使用numpy数组时,求和版本不起作用,它会显示错误消息:“函数无法缩减” - 我稍微晚了一点编辑了numpy数组的细节,抱歉。 - rammelmueller

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