[英]Minimum per group with condition
考虑下面的dataframe
d
:
d = pd.DataFrame({
'id': ['A', 'A', 'A', 'B', 'B', 'B'],
'name': ['a', 'b', 'd', 'a', 'c', 'e'],
'value': [10, 8, 9, 11, 3, 5],
})
我添加了一个空列d['col'] = pd.Series()
所以d
看起来像:
id name value col
0 A a 10 NaN
1 A b 8 NaN
2 A d 9 NaN
3 B a 11 NaN
4 B c 3 NaN
5 B e 5 NaN
我现在想将d.col
设置为True
如果对于d.id
定义的每个组,如果此条件成立:
d.value[d.name!='a'].min()
最终结果将如下所示:
id name value col
0 A a 10 NaN
1 A b 8 True
2 A d 9 NaN
3 B a 11 NaN
4 B c 3 True
5 B e 5 NaN
我怀疑我需要以某种方式使用d.groupby('id').apply()
,但无法通过设置条件来正确处理。
编辑:我对任何巧妙的解决方案持开放态度。 重要的是,我希望能够根据排除name=='a'
条件,为每个组选择一个“获胜者”(其中d.col==True
)。
您可以通过按位&
链接结果来groupby
和转换min
检查name
不是a
:
# updated, thx @piR and @quang
d['col'] = d.groupby('id').value.transform('min').eq(d.value) & d.name.ne('a')
根据您的更新,如果您只想“选择获胜者”,让我们保留第一场比赛以保持简单。 因此,取idxmin
,与索引(假设唯一索引)进行比较,并与上述其他条件进行链接:
d['col'] = d.groupby('id').value.transform('idxmin').eq(d.index) & d.name.ne('a')
print(d)
id name value col
0 A a 10 False
1 A b 8 True
2 A d 9 False
3 B a 11 False
4 B c 3 True
5 B e 5 False
一种方法是使用map
:
min_values = d[d['name']!='a'].groupby('id')['value'].min()
d['col'] = d['value'] == d['id'].map(min_values)
Output:
id name value col
0 A a 10 NaN
1 A b 8 1.0
2 A d 9 NaN
3 B a 11 NaN
4 B c 3 1.0
5 B e 5 NaN
一旦选择了名称不等于ne
到 'a' 的所有行,您就可以使用sort_values
和drop_duplicates
来做到这一点,例如:
d.loc[d[d['name'].ne('a')].sort_values('value').drop_duplicates('id').index, 'col'] = 1
print (d)
id name value col
0 A a 10 NaN
1 A b 8 1.0
2 A d 9 NaN
3 B a 11 NaN
4 B c 3 1.0
5 B e 5 NaN
这是一个简单的示例,到目前为止,四种解决方案(来自@Quang 、 @Yatu和我的)如何在其他情况下给出与来自 OP 的原始输入数据不同的结果:
# add id C and D with specific values
d = pd.DataFrame({
'id': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D'],
'name': ['a', 'b', 'd', 'a', 'c', 'e', 'a', 'f', 'g', 'a', 'h', 'i'],
'value': [10, 8, 9, 11, 3, 5, 2, 5, 10, 12, 6, 6],
})
#Quang
min_values = d[d['name']!='a'].groupby('id')['value'].min()
d['col_Quang'] = d['value'] == d['id'].map(min_values)
#Yatu
d['col_Yatu_min'] = d.groupby('id').value.transform('min').eq(d.value) & d.name.ne('a')
d['col_Yatu_idx'] = d.groupby('id').value.transform('idxmin').eq(d.index) & d.name.ne('a')
# mine
d.loc[d[d['name'].ne('a')].sort_values('value').drop_duplicates('id').index, 'col_ben'] = True
print (d)
id name value col_Quang col_Yatu_min col_Yatu_idx col_ben
0 A a 10 False False False NaN
1 A b 8 True True True True
2 A d 9 False False False NaN
3 B a 11 False False False NaN
4 B c 3 True True True True
5 B e 5 False False False NaN
6 C a 2 False False False NaN
7 C f 5 True False False True
8 C g 10 False False False NaN
9 D a 12 False False False NaN
10 D h 6 True True True True
11 D i 6 True True False NaN
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.