Pandas:如何在函数内将 sum() 或 mean() 分配给 df.groupby?

ves*_*and 5 python function pandas

我想换df.groupby(pd.TimeGrouper(freq='M')).sum()一个函数,这样我可以分配sum()mean()count()在该函数的参数。我之前在这里问过一个类似的问题,但我认为在这种特殊情况下我不能使用相同的技术。

这是一个具有可重现输入的片段:

# Imports
import pandas as pd
import numpy as np

# Dataframe with 1 or zero
# 100 rows and 4 columns
# Indexed by dates
np.random.seed(12345678)
df = pd.DataFrame(np.random.randint(0,2,size=(100, 4)), columns=list('ABCD'))
datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=100).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
print(df.head(10))
Run Code Online (Sandbox Code Playgroud)

这使:

在此处输入图片说明

有了这个,我们可以做到:

df2 = df.groupby(pd.TimeGrouper(freq='M')).sum()
print(df2)
Run Code Online (Sandbox Code Playgroud)

并得到:

在此处输入图片说明

或者我们可以这样做:

df3 = df.groupby(pd.TimeGrouper(freq='M')).mean()
print(df3)
Run Code Online (Sandbox Code Playgroud)

并得到:

在此处输入图片说明

这是包装成函数的过程的一部分:

# My function
def function1(df):
    df = df.groupby(pd.TimeGrouper(freq='M')).sum()
    return df

# Function1 call
df4 = function1(df = df)
print(df4)
Run Code Online (Sandbox Code Playgroud)

这工作得很好:

在此处输入图片说明

当我尝试在 Function2 中添加sum()mean()作为参数时会出现问题,如下所示:

# My function with sum() as an argument
def function2(df, fun):
    df = df.groupby(pd.TimeGrouper(freq='M')).fun
    return df
Run Code Online (Sandbox Code Playgroud)

我的第一次尝试引发了一个 TypeError:

# Function2 test 1
df5 = function2(df = df, fun = sum())
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我的第二次尝试引发了一个属性错误:

# Function2 test 2
df6 = function2(df = df, fun = 'sum()')
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

是否可以对此设置进行一些调整以使其正常工作?(我尝试了另一个版本,以 'M' 作为 freq 的参数,效果很好)。或者这不是这些事情的处理方式?

感谢您的任何建议!

这是一个简单的复制和粘贴的混乱:

#%%

# Imports
import pandas as pd
import numpy as np

# Dataframe with 1 or zero
# 100 rows across 4 columns
# Indexed by dates
np.random.seed(12345678)
df = pd.DataFrame(np.random.randint(0,2,size=(100, 4)), columns=list('ABCD'))
datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=100).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
print(df.head(10))

# Calculate sum per month
df2 = df.groupby(pd.TimeGrouper(freq='M')).sum()
print(df2)

# Or calculate average per month
df3 = df.groupby(pd.TimeGrouper(freq='M')).mean()
print(df3)

# My function
def function1(df):
    df = df.groupby(pd.TimeGrouper(freq='M')).sum()
    return df

# Function1 test
df4 = function1(df = df)
print(df4)
# So far so good
#%%
# My function with sum() as argument
def function2(df, fun):
    print(fun)
    df = df.groupby(pd.TimeGrouper(freq='M')).fun
    return df

# Function2 test 1
# df5 = function2(df = df, fun = sum())

# Function2 test 2
# df6 = function2(df = df, fun = 'sum()')

# Function2 test 3
# df7 = function2(df = df, fun = sum)
Run Code Online (Sandbox Code Playgroud)

piR*_*red 5

你需要使用 apply

def function2(df, fun):
    return df.groupby(pd.TimeGrouper(freq='M')).apply(fun)
Run Code Online (Sandbox Code Playgroud)

只要确保fun是一个需要pd.DataFrame


但是,您可能应该使用agg. 如果fun将列减少到类似于sum或的标量mean,那么这应该有效。需要考虑的事情。

df.groupby(pd.TimeGrouper('M')).agg(['sum', 'mean', fun])
Run Code Online (Sandbox Code Playgroud)

  • @vestland 如果您使用我的建议来使用 apply,那么 fun 必须是一个函数。'mean' 是一个字符串。np.mean 是一个函数。该函数还必须将数据帧作为第一个参数并返回熊猫可以处理的内容。np.mean 接受一个数据帧,作用于值并返回整个数组的平均值。我不确定 np.count 做了什么。'count' 是一个字符串,不起作用。您最好发布一个新问题,提供有关您要执行的操作的更多详细信息。 (2认同)