Pandas从几个group-by操作创建新的数据帧

2024-09-28 14:57:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有熊猫数据帧

test = pd.DataFrame({'d':[1,1,1,2,2,3,3], 'id':[1,2,3,1,2,2,3], 'v1':[10, 20, 15, 35, 5, 10, 30], 'v2':[3, 4, 1, 6, 0, 2, 0], 'w1':[0.1, 0.3, 0.2, 0.1, 0.4, 0.3, 0.2], 'w2':[0.8, 0.1, 0.2, 0.3, 0.1, 0.1, 0.0]})


    d   id  v1  v2  w1  w2
0   1   1   10  3   0.10    0.80
1   1   2   20  4   0.30    0.10
2   1   3   15  1   0.20    0.20
3   2   1   35  6   0.10    0.30
4   2   2   5   0   0.40    0.10
5   3   2   10  2   0.30    0.10
6   3   3   30  0   0.20    0.00

我想得到一些加权值

^{pr2}$

我怎样才能把结果很好地输入df。看起来像

test.groupby('id').sum()['w1v1'] / test.groupby('id').sum()['w1']

id
1   22.50
2   11.00
3   22.50

但是包含每个加权值的列,就像

id   w1v1 w1v2 w2v1 w2v2
1   22.50  ...  ...  ...
2   11.00  ...  ...  ...
3   22.50  ...  ...  ...

有什么办法让我轻松快捷地完成这个任务吗?在


Tags: 数据testiddataframedfw1v2pd
2条回答

使用:

cols = ['w1v1','w1v2','w2v1','w2v2'] 
test1  =  (test[['w1', 'w2', 'w1', 'w2']] * test[['v1', 'v1', 'v2', 'v2']].values)
test1.columns = cols
print (test1)
   w1v1  w1v2  w2v1  w2v2
0   1.0   8.0   0.3   2.4
1   6.0   2.0   1.2   0.4
2   3.0   3.0   0.2   0.2
3   3.5  10.5   0.6   1.8
4   2.0   0.5   0.0   0.0
5   3.0   1.0   0.6   0.2
6   6.0   0.0   0.0   0.0

df = test.join(test1).groupby('id').sum()
df1  =  df[cols] / df[['w1', 'w2', 'w1', 'w2']].values
print (df1)
    w1v1       w1v2  w2v1      w2v2
id                                 
1   22.5  16.818182   4.5  3.818182
2   11.0  11.666667   1.8  2.000000
3   22.5  15.000000   0.5  1.000000

另一个使用MultiIndex DataFrames的更动态的解决方案:

^{pr2}$
df = w * v
print (df)
     v1         v2     
     w1    w2   w1   w2
id                     
1   1.0   8.0  0.3  2.4
2   6.0   2.0  1.2  0.4
3   3.0   3.0  0.2  0.2
1   3.5  10.5  0.6  1.8
2   2.0   0.5  0.0  0.0
2   3.0   1.0  0.6  0.2
3   6.0   0.0  0.0  0.0

df1 = df.groupby('id').sum() / w.groupby('id').sum()
#flatten MultiIndex columns
df1.columns = ['{0[1]}{0[0]}'.format(x) for x in df1.columns]
print (df1)
    w1v1       w2v1  w1v2      w2v2
id                                 
1   22.5  16.818182   4.5  3.818182
2   11.0  11.666667   1.8  2.000000
3   22.5  15.000000   0.5  1.000000

如果可以获取多索引列,则可以使用groupby + dot

test.groupby('id').apply(
    lambda g: g.filter(like='v').T.dot(g.filter(like='w')/g.filter(like='w').sum()).stack()
)

#      v1              v2          
#      w1         w2   w1        w2
#id                                
#1   22.5  16.818182  4.5  3.818182
#2   11.0  11.666667  1.8  2.000000
#3   22.5  15.000000  0.5  1.000000

相关问题 更多 >