在 Pandas 中有效地分组、编辑和重新加入组
Grouping, editing, and re-joining groups efficiently in Pandas
在 pandas 中,我一直在寻找一种通用流程,按特定列对数据帧进行分组,对这些组执行重要的操作,然后将这些组重新组合回一个大数据帧(通过有效地将它们堆叠在一起)。
假设我有一个 DataFrame df
:
+----+-------+---+---+---+
| | A | B | C | D |
+----+-------+---+---+---+
| 0 | Green | 1 | 4 | 5 |
| 1 | Red | 2 | 3 | 2 |
| 2 | Red | 1 | 4 | 3 |
| 3 | Green | 2 | 2 | 2 |
| 4 | Green | 1 | 1 | 1 |
| 5 | Blue | 2 | 1 | 5 |
| 6 | Red | 2 | 1 | 6 |
| 7 | Blue | 7 | 8 | 9 |
| 8 | Green | 7 | 6 | 5 |
| 9 | Red | 0 | 9 | 0 |
| 10 | Blue | 4 | 5 | 4 |
+----+-------+---+---+---+
我想对A列进行groupby()操作,然后对每一组进行操作。通常,此操作涉及通过将一行中的值与该行中的值进行比较来为所有行创建新行,因此我不会说它可以通过应用于组的 lambda 函数来完成。然后,我想将这些组重新组合到数据框中,有效地采用与上面相同的格式,但带有插入的行。
到目前为止,我的一般方法是 "slow and stupid" 方式,即:
group_list = []
g = df.groupby("A")
for i, group in g:
###Perform some weird operation on group that can't really be reduced to a
#lambda function applied to each group.
group_list.append(group)
reconstituted = group_list[0]
for i in range(1,len(group_list)):
reconstituted = reconstituted.append(group_list[i], ignore_index=True)
显然,这并不是特别 pandas 风格,所以这是我的问题 - 对群体本身进行操作然后重建它们的更好方法是什么?
在不知道你的函数做什么的情况下,如果你只想加入它们,你可以使用 pd.concat
:
df_new = pd.concat(group_list)
MVCE:
In [77]: df1
Out[77]:
0
0 a
1 b
In [78]: df2
Out[78]:
0
0 c
1 d
In [79]: pd.concat([df1, df2], ignore_index=True)
Out[79]:
0
0 a
1 b
0 c
1 d
但是,我建议您考虑一种不同的技术,它不涉及显式拆分组并分别处理它们,这是非常低效的。
下面的代码可以根据A列的值提取值
import pandas as pd
df = pd.DataFrame([{'A': 'Green', 'B': 1}, {'A': 'Red', 'B': 2}, {'A': 'Green', 'B': 3}])
for value in df.A.unique():
print(df[df.A == value])
如果不想合并回df,可以直接按A列排序
df.sort_values("A")
你可以得到如下结果:
A B
0 Green 1
2 Green 3
1 Red 2
在 pandas 中,我一直在寻找一种通用流程,按特定列对数据帧进行分组,对这些组执行重要的操作,然后将这些组重新组合回一个大数据帧(通过有效地将它们堆叠在一起)。
假设我有一个 DataFrame df
:
+----+-------+---+---+---+
| | A | B | C | D |
+----+-------+---+---+---+
| 0 | Green | 1 | 4 | 5 |
| 1 | Red | 2 | 3 | 2 |
| 2 | Red | 1 | 4 | 3 |
| 3 | Green | 2 | 2 | 2 |
| 4 | Green | 1 | 1 | 1 |
| 5 | Blue | 2 | 1 | 5 |
| 6 | Red | 2 | 1 | 6 |
| 7 | Blue | 7 | 8 | 9 |
| 8 | Green | 7 | 6 | 5 |
| 9 | Red | 0 | 9 | 0 |
| 10 | Blue | 4 | 5 | 4 |
+----+-------+---+---+---+
我想对A列进行groupby()操作,然后对每一组进行操作。通常,此操作涉及通过将一行中的值与该行中的值进行比较来为所有行创建新行,因此我不会说它可以通过应用于组的 lambda 函数来完成。然后,我想将这些组重新组合到数据框中,有效地采用与上面相同的格式,但带有插入的行。
到目前为止,我的一般方法是 "slow and stupid" 方式,即:
group_list = []
g = df.groupby("A")
for i, group in g:
###Perform some weird operation on group that can't really be reduced to a
#lambda function applied to each group.
group_list.append(group)
reconstituted = group_list[0]
for i in range(1,len(group_list)):
reconstituted = reconstituted.append(group_list[i], ignore_index=True)
显然,这并不是特别 pandas 风格,所以这是我的问题 - 对群体本身进行操作然后重建它们的更好方法是什么?
在不知道你的函数做什么的情况下,如果你只想加入它们,你可以使用 pd.concat
:
df_new = pd.concat(group_list)
MVCE:
In [77]: df1
Out[77]:
0
0 a
1 b
In [78]: df2
Out[78]:
0
0 c
1 d
In [79]: pd.concat([df1, df2], ignore_index=True)
Out[79]:
0
0 a
1 b
0 c
1 d
但是,我建议您考虑一种不同的技术,它不涉及显式拆分组并分别处理它们,这是非常低效的。
下面的代码可以根据A列的值提取值
import pandas as pd
df = pd.DataFrame([{'A': 'Green', 'B': 1}, {'A': 'Red', 'B': 2}, {'A': 'Green', 'B': 3}])
for value in df.A.unique():
print(df[df.A == value])
如果不想合并回df,可以直接按A列排序
df.sort_values("A")
你可以得到如下结果:
A B
0 Green 1
2 Green 3
1 Red 2