繁体   English   中英

每组最低条件

[英]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_valuesdrop_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM