Python 熊猫:使用多个函数聚合多个列

Python 熊猫:使用多个函数聚合多个列,python,r,pandas,dplyr,Python,R,Pandas,Dplyr,Python中的Pandas和R中的Dplyr都是灵活的数据争用工具。例如,在R中,使用dplyr可以执行以下操作: custom_func <- function(col1, col2) length(col1) + length(col2) ChickWeight %>% group_by(Diet) %>% summarise(m_weight = mean(weight), var_time = var(Time),

Python中的Pandas和R中的Dplyr都是灵活的数据争用工具。例如,在R中,使用dplyr可以执行以下操作:

custom_func <- function(col1, col2) length(col1) + length(col2)

ChickWeight %>% 
  group_by(Diet) %>% 
  summarise(m_weight = mean(weight), 
            var_time = var(Time), 
            covar = cov(weight, Time),
            odd_stat = custom_func(weight, Time))
自定义函数%
组(饮食)%>%
总结(m_重量=平均(重量),
var_时间=var(时间),
covar=cov(重量、时间),
奇数统计=自定义函数(重量、时间))
注意如何在一个语句中

  • 我可以在一行中聚合多个列
  • 我可以在一行中对这些多列应用不同的函数
  • 我可以使用考虑两列的函数
  • 我可以为其中任何一个添加自定义函数
  • 我可以为这些聚合声明新列名

这种模式在熊猫身上也可能吗?请注意,我有兴趣在一个简短的语句中这样做(因此不要创建三个不同的数据帧,然后连接它们)。

自0.16.0版以来,pandas提供了
assign()
方法。我不确定它与@akrun提到的熊猫皮相比到底有什么不同,但它是熊猫的一部分。我认为除了groupby部分(或者我只是不知道如何与groupby结合)之外,它可以满足您的所有需求

受dplyr的mutate verb启发,DataFrame有一个新的assign()方法。assign的函数签名只是**kwargs。键是新字段的列名,值可以是要插入的值(例如,一个系列或NumPy数组),也可以是要在数据帧上调用的一个参数的函数。插入新值,并返回整个数据帧(包括所有原始列和新列)

查看您的示例代码,我不确定如何执行groupby,但您肯定可以执行这类操作。(事实上,如果我想不出来,我可能会发布一个后续问题。)

或者,可以这样做:

df.assign( mean_weight = df['weight'].mean(),
           var_time    = df['time'].var(),
           covar       = np.cov(df['t1'],df['t2'])[0,0] )
或者,您可以像这样包含groupby(混合以下可选方式):

但是你必须做一个groupby 4x,而不是1x,所以这不是一个真正令人满意的解决方案

我将进一步研究该语法,看看是否可以使它更接近您的示例(您可能希望提供示例数据以获得更好的答案)

或者,您可以使用标准的groupby技术来获得答案,但我认为这需要多条语句(不能只执行一条长链行)由于复杂性--您的一些分配可以与groupby的
agg
组合,但我认为用户功能无法组合。

使用pandas,您可以在groupby聚合中运行多个功能。请注意,您需要安装
scipy
的统计功能。对于自定义函数,需要为groupwise数据运行聚合,如
sum()

def customfct(x,y):
    data = x / y
    return data.mean()

def f(row):  
    row['m_weight'] = row['weight'].mean()
    row['var_time'] = row['Time'].var()
    row['cov'] = row['weight'].cov(row['Time'])
    row['odd_stat'] = customfct(row['weight'], row['Time'])
    return row

aggdf = df.groupby('Diet').apply(f)
我在这里向您介绍如何将R代码翻译成python:

来自pipda导入寄存器的
>>\u func
>>>从数据R.所有输入f、长度、分组依据、汇总、平均值、var、cov
>>>从datar.dataset导入权重
>>> 
>>>@register_func(无)
... 定义自定义函数(col1、col2):
...     返回长度(col1)+长度(col2)
... 
>>>鸡体重>>\
...     分组依据(膳食)>>\
...     总结(
…m_重量=平均值(f重量),
…var_time=var(f.time),
…covar=cov(f.重量,f.时间),
…奇数统计=自定义函数(f.重量,f.时间)
...     )
饮食m_体重变化时间covar奇数统计
0       1  102.645455  45.422397  312.189871       440
1       2  122.616667  45.909722  398.564426       240
2       3  142.950000  45.909722  528.827731       240
3       4  135.262712  45.100618  441.868535       236

我是这个包裹的作者。如果您有任何问题,请随时提交问题。

您可以检查项目是否令人印象深刻,但我想知道这样的事情在base-pandas中是否可行。您在说什么?链接有基本pandas方法。对于基本pandas,我的意思是如果这在pandas中是可能的,而不是必须在顶部添加一个包。另外,这个包有github吗?@akrun,如果你能将评论写到一个解决方案中,我会接受它作为问题的答案。你可以做
df.groupby('diet')。apply(lambda x:x.assign(…)
,并在1 groupby中获得你想要的东西。这就是说,使用apply once确实(而且似乎仍然)使操作变慢了。@VernepatorCur好的,谢谢,我稍后会尝试一下
df.assign( mean_weight = df['weight'].groupby(df.diet).transform('mean'),
           var_time    = lambda x: x['time'].groupby(x['diet']).transform('mean') )
def customfct(x,y):
    data = x / y
    return data.mean()

def f(row):  
    row['m_weight'] = row['weight'].mean()
    row['var_time'] = row['Time'].var()
    row['cov'] = row['weight'].cov(row['Time'])
    row['odd_stat'] = customfct(row['weight'], row['Time'])
    return row

aggdf = df.groupby('Diet').apply(f)