Python 3.x 从groupby创建DataFrame列
假设我有一个像Python 3.x 从groupby创建DataFrame列,python-3.x,pandas,dataframe,pandas-groupby,Python 3.x,Pandas,Dataframe,Pandas Groupby,假设我有一个像 import pandas as pd df = pd.DataFrame({ 'Id' : [1,2,3,4,5,6,7,8,9], 'Group' : [1,1,2,2,2,2,3,3,3], 'Value_to_compare' : [2,1,5,8,2,3,10,23,17], 'Other_value' : [0,3,2,6,3,4,2,7,1] }) 我想创建一个新列,比如说Value\u of_Highest,为其组的值最高的
import pandas as pd
df = pd.DataFrame({
'Id' : [1,2,3,4,5,6,7,8,9],
'Group' : [1,1,2,2,2,2,3,3,3],
'Value_to_compare' : [2,1,5,8,2,3,10,23,17],
'Other_value' : [0,3,2,6,3,4,2,7,1]
})
我想创建一个新列,比如说Value\u of_Highest
,为其组的值最高的元素的每一行其他\u值
显示。例如,这里:
- 组1有2个元素,其最高
值\u to \u compare
为2,对于Id
=1,其其他\u值
为0
- 第2组有4个元素,最高的
Value\u to\u compare
为8,对于Id
=4,其中其他值为6
- 第3组有3个元素,最高的
值\u to \u compare
为23,对于Id
=8,其中其他\u值
为7
因此,我想添加一列,使df成为
这是我知道的最好的方法:
def my_func(x):
x = x.sort_values('Value_to_compare',ascending = False)
Value_of_Highest = x.head(1)['Other_value'].values[0]
return pd.Series([Value_of_Highest], index=['Value_of_Highest'])
grouped = df.groupby('Group').apply(my_func).reset_index()
df = df.merge(grouped)
我敢肯定,在Python/Pandas中有一种更优雅、更高效的方法来实现这一点
编辑:在@CameronRiddell给出第一个答案后,我意识到我的例子有缺陷。我更正了它,@CameronRiddell编辑了他的答案,效果很好。这是groupby
和transform
的一个很好的应用,本质上,使用groupby对象的transform将函数应用于每个组,但随后返回与该组大小相同的序列或数据帧。这将导致数据帧/系列的形状与groupby轴上的原始形状相同。(例如,在您的情况下,groupby/转换的结果将具有与原始数据帧相同的行数)
df.groupby(“Group”)
:按“Group”列对数据帧进行分组
[“值与值比较”]
:从每个组中选择“值与值比较”列
.transform(“max”)
:获取每个组所选列的最大值。然后返回与组具有相同行数的序列
编辑:为了根据最大值的位置获得一个值,我们使用idxmax()
。这将返回发生最大/最小值的位置。因此,对于我们的用例:
- 我们将按“组”分组,并选择“值比较”列
- 然后我们得到“值与值比较”的最大值的索引
0、3、7对应于行ID,在该行ID中,每个组中出现“Value_to_compare”的最大值
现在我们知道了这些最大值发生在:
- 我们需要对原始数据帧进行子集,以获得每一行中的“其他值”
- 我们还需要获得与这些行相关联的“Group”列,以便以后能够正确地对齐这些值
现在,我们已经将每个组对应的“其他值”设置为最大的“值比较”,我们将使用合并
将新的较小数据帧与原始数据帧对齐。这将在原始数据帧的“组”列中广播“最高值”
df["Value_of_Highest"] = df.groupby("Group")["Value_to_compare"].transform("max")
print(df)
Id Group Value_to_compare Other_value Value_of_Highest
0 1 1 2 0 2
1 2 1 1 3 2
2 3 2 5 2 8
3 4 2 8 6 8
4 5 2 2 3 8
5 6 2 3 4 8
6 7 3 10 2 23
7 8 3 23 7 23
8 9 3 17 1 23
# Merge this new dataframe back to our old one to broadcast "Value_of_Highest" across each group
final = df.merge(highest_other_values, on="Group")
print(final)
Id Group Value_to_compare Other_value Value_of_Highest
0 1 1 2 0 0
1 2 1 1 3 0
2 3 2 5 2 6
3 4 2 8 6 6
4 5 2 2 3 6
5 6 2 3 4 6
6 7 3 10 2 7
7 8 3 23 7 7
8 9 3 17 1 7
这是groupby
和transform
的一个很好的应用,本质上,使用groupby对象的transform将函数应用于每个组,但随后返回与该组大小相同的序列或数据帧。这将导致数据帧/系列的形状与groupby轴上的原始形状相同。(例如,在您的情况下,groupby/转换的结果将具有与原始数据帧相同的行数)
df.groupby(“Group”)
:按“Group”列对数据帧进行分组
[“值与值比较”]
:从每个组中选择“值与值比较”列
.transform(“max”)
:获取每个组所选列的最大值。然后返回与组具有相同行数的序列
编辑:为了根据最大值的位置获得一个值,我们使用idxmax()
。这将返回发生最大/最小值的位置。因此,对于我们的用例:
- 我们将按“组”分组,并选择“值比较”列
- 然后我们得到“值与值比较”的最大值的索引
0、3、7对应于行ID,在该行ID中,每个组中出现“Value_to_compare”的最大值
现在我们知道了这些最大值发生在:
- 我们需要对原始数据帧进行子集,以获得每一行中的“其他值”
- 我们还需要获得与这些行相关联的“Group”列,以便以后能够正确地对齐这些值
现在,我们已经将每个组对应的“其他值”设置为最大的“值比较”,我们将使用合并
将新的较小数据帧与原始数据帧对齐。这将在原始数据帧的“组”列中广播“最高值”
df["Value_of_Highest"] = df.groupby("Group")["Value_to_compare"].transform("max")
print(df)
Id Group Value_to_compare Other_value Value_of_Highest
0 1 1 2 0 2
1 2 1 1 3 2
2 3 2 5 2 8
3 4 2 8 6 8
4 5 2 2 3 8
5 6 2 3 4 8
6 7 3 10 2 23
7 8 3 23 7 23
8 9 3 17 1 23
# Merge this new dataframe back to our old one to broadcast "Value_of_Highest" across each group
final = df.merge(highest_other_values, on="Group")
print(final)
Id Group Value_to_compare Other_value Value_of_Highest
0 1 1 2 0 0
1 2 1 1 3 0
2 3 2 5 2 6
3 4 2 8 6 6
4 5 2 2 3 6
5 6 2 3 4 6
6 7 3 10 2 7
7 8 3 23 7 7
8 9 3 17 1 7
哇!我想你救了我的代码伙伴!!!非常感谢你!不过,这并不完全是因为你将值复制到了\u compare
而不是其他值。我进行了编辑,因此它显示了Other\u value
中的值,而不是value\u to\u compare
。我还是迷路了,你能帮忙吗?我已经更新了我的答案来解决这个问题!(保留我原来的答案,并将新答案放在下面)太好了,真的非常感谢!下次我需要这种东西时,我会考虑idmax()哇!我想你救了我的代码伙伴!!!非常感谢你!不过,这并不完全是因为你将值复制到了\u compare
而不是其他值。我进行了编辑,因此它显示了Other\u value
中的值,而不是value\u to\u compare
。我还是迷路了,你能帮忙吗?我已经更新了我的答案来解决这个问题!(保留我原来的答案,并将新答案放在下面)太好了,比