Python pandas groupby:如何使用不同列中的变量创建一个新列

问题描述 投票:0回答:3

考虑以下

DataFrame

df = pd.DataFrame({'c0':['1980']*3+['1990']*2+['2000']*3,
                   'c1':['x','y','z']+['x','y']+['x','y','z'],
                   'c2':range(8)  })

     c0 c1  c2
0  1980  x   0
1  1980  y   1
2  1980  z   2
3  1990  x   3
4  1990  y   4
5  2000  x   5
6  2000  y   6
7  2000  z   7

我想用

pandas
groupby
c0
上做以下事情:

  1. Group rows based on
    c0
    (indicate year).
  2. 在每组中,从
    c2
    的值中减去
    y
    c1
    (在
    c2
    中)的值。
  3. 添加新列
    c3
    收集这些值。

最后的结果是

     c0 c1  c2  c3
0  1980  x   0  -1
1  1980  y   1   0
2  1980  z   2   1
3  1990  x   3  -1
4  1990  y   4   0
5  2000  x   5  -1
6  2000  y   6   0
7  2000  z   7   1

我能够在没有

groupby
的情况下得到如下结果:

dic = {}

for yr in df['c0'].unique():
    
    cond1 = ( df['c0']==yr )
    tmp = df.loc[cond1,:].copy()
    
    cond2 = ( tmp['c1']=='y' )
    val = tmp.loc[cond2,'c2'].to_numpy()
    
    tmp['c3'] = tmp['c2'] - val
    
    dic[yr] = tmp


pd.concat([dic['1980'],dic['1990'],dic['2000']])

它有效但看起来不太好。我尝试了

transform
apply
groupby
,但无法弄清楚。任何帮助将不胜感激。

python pandas dataframe group-by
3个回答
1
投票

在使用

y
隐藏组的所有非 y 行后,您可以使用
transform
广播
where
值:

df['c3' ] = df['c2'] - df.where(df['c1'] == 'y').groupby(df['c0'])['c2'].transform('max')
print(df)

# Output
     c0 c1  c2   c3
0  1980  x   0 -1.0
1  1980  y   1  0.0
2  1980  z   2  1.0
3  1990  x   3 -1.0
4  1990  y   4  0.0
5  2000  x   5 -1.0
6  2000  y   6  0.0
7  2000  z   7  1.0

1
投票

这是多索引选择的新功能

s = df.set_index(['c0', 'c1'])
s['c3'] = s['c2'] - s['c2'].xs('y', level=1)
s = s.reset_index()

结果

     c0 c1  c2  c3
0  1980  x   0  -1
1  1980  y   1   0
2  1980  z   2   1
3  1990  x   3  -1
4  1990  y   4   0
5  2000  x   5  -1
6  2000  y   6   0
7  2000  z   7   1

0
投票

另一种可能的解决方案:

df['c3'] = (df.groupby('c0')
            .apply(lambda g: g['c2'].values-g.loc[g['c1'].eq('y'), 'c2'].values)
            .explode().values)

输出:

     c0 c1  c2  c3
0  1980  x   0  -1
1  1980  y   1   0
2  1980  z   2   1
3  1990  x   3  -1
4  1990  y   4   0
5  2000  x   5  -1
6  2000  y   6   0
7  2000  z   7   1
© www.soinside.com 2019 - 2024. All rights reserved.