Python相当于groupby mutate
因此,在R中,当我有一个由4列组成的数据框,称之为df,我想通过一个组的和积来计算比率,我可以这样做:Python相当于groupby mutate,python,r,pandas,dplyr,Python,R,Pandas,Dplyr,因此,在R中,当我有一个由4列组成的数据框,称之为df,我想通过一个组的和积来计算比率,我可以这样做: // generate data df = data.frame(a=c(1,1,0,1,0),b=c(1,0,0,1,0),c=c(10,5,1,5,10),d=c(3,1,2,1,2)); | a b c d | | 1 1 10 3 | | 1 0 5 1 | | 0 0 1 2 | | 1 1 5 1 | | 0
// generate data
df = data.frame(a=c(1,1,0,1,0),b=c(1,0,0,1,0),c=c(10,5,1,5,10),d=c(3,1,2,1,2));
| a b c d |
| 1 1 10 3 |
| 1 0 5 1 |
| 0 0 1 2 |
| 1 1 5 1 |
| 0 0 10 2 |
// compute sum product ratio
df = df%>% group_by(a,b) %>%
mutate(
ratio=c/sum(c*d)
);
| a b c d ratio |
| 1 1 10 3 0.286 |
| 1 1 5 1 0.143 |
| 1 0 5 1 1 |
| 0 0 1 2 0.045 |
| 0 0 10 2 0.454 |
但在python中,我需要求助于循环。
我知道python中应该有一种比原始循环更优雅的方式,有人有什么想法吗 可以使用与
groupby()
和apply()
类似的语法来完成:
根据这一点,我们可以使用transform()
方法复制dplyr::groupby()
和dplyr::mutate()
的组合。对于本例,它将如下所示:
df=pd.DataFrame(
口述(
a=(1,1,0,1,0),
b=(1,0,0,1,0),
c=(10,5,1,5,10),
d=(3,1,2,1,2),
)
).分配(
prod_c_d=lambda x:x['c']*x['d'],
比率=λx:x['c']/(x.groupby(['a','b'])。转换('sum')['prod_c_d']))
)
本例使用。有关如何使用方法链接复制dplyr
工作流的更多信息,请参见此
使用apply()
和groupby()。例如,如果我们从lambda表达式中删除g.c/
,则它不起作用
df['ratio'] = df.groupby(['a','b'], group_keys=False)\
.apply(lambda g: (g.c * g.d).sum() )
group_keys=False实现了什么?默认情况下,groupby()
将组列作为额外索引添加到结果中,这使得其索引不同于原始数据帧,因此无法轻松为其分配数据帧。避免将组列添加为键,这样,只要每一行都有唯一的索引,就可以进行赋值。好吧,这和mutate一样实用。mutate的最大优点是,您可以在pipiline中创建一个新变量并保持链接,而这需要您专门指定一行来指定新列。难道没有一个“inplace=True”的方法来为panda创建一个额外的列吗?如果我们想在同一个调用中分配两个以上的列,每个列都使用.groupby(['a','b'])
?有没有比像这样对每一列重复groupby方法更“整洁”的方法df=df.assign(c_lag1=lambda x:x['c'].groupby(['a','b']).shift(-1),c_lag2=lambda x:x['c'].groupby(['a','b']).shift(-2))
您能否进一步解释为什么我们需要分配中的lambda
?我搞不懂x
指的是什么。原始DataFrame
或某些子组?lambda表达式是编写一行一个关键字函数的方法。在assign
方法x
中使用它时,调用原始数据帧,其中包含当前方法链上游已经进行的所有更改。这仍然是最好的方法吗?在熊猫1.0中有更好的方法吗?…,这种方法是我发现的最好的方法,但是它似乎不是很有效(当你只需要一列时,对所有列进行转换('sum'))。mutate的另一个真正强大的部分是不需要作用域,你可以简单地编写c/sum(cd)它知道它指的是来自左边的数据帧。我觉得用python编写lambda g:g.c/(g.cg.d).sum()@jedi是没有必要的冗长和混乱的,我同意,但当你不得不使用python时,你无能为力。。。
df['ratio'] = df.groupby(['a','b'], group_keys=False)\
.apply(lambda g: (g.c * g.d).sum() )