在 pandas 中需要高效 groupby 的帮助
Need help for efficient groupby in pandas
我有以下 df,其中包含有关客户、活动日期和花费价值的信息:
pandas dataframe
重现 df 的代码:
d = {'CLIENT': ['John', 'Jonas', 'Mary', 'Anne', 'John', 'Jonas', 'Mary','John', 'Mary'],'SPENT': [30, 400, 800, 90, 180, 560, 50, 200, 100],'DAY_EVENT': ['WED', 'SAT', 'SUN', 'MON', 'FRI', 'WED', 'THU', 'FRI', 'SUN']}
df = pd.DataFrame(data=d)
我首先使用以下聚合选项制作了一个 df.groupby
:
df_cli = df.groupby('CLIENT').agg({'SPENT': [np.size, np.sum, np.mean]}).reset_index()
这给我留下了这个:
pandas groupby dataframe
我想确定我的客户最喜欢和最不喜欢的日子,但我不知道如何使它成为 groupby
函数的变量,所以我尝试了另一个 groupby
df:
df_cli_day = df.groupby(['CLIENT','DAY_EVENT']).agg({'SPENT':[np.size, np.sum, np.mean]}).reset_index(level=1)
然后我有这个:
another pandas groupby dataframe
我尝试过定义函数,然后将它们应用于数据框,如下所示:
def preferred_day(row):
cli = df_cli['CLIENT'][row]
clidays = df_cli_day.loc[cli]
return clidays['DAY_EVENT'].max()
def least_preferred_day(row):
cli = df_cli['CLIENT'][row]
clidays = df_cli_day.loc[cli]
return clidays['DAY_EVENT'].min()
df_cli['preferred_day'] = df_cli.apply(lambda row: preferred_day(row), axis=1)
这引发了以下问题:
ValueError: ('cannot index with vector containing NA / NaN values', 'occurred at index 0')
由于我的函数在调用时起作用,所以我通过循环并将结果附加到列表,然后将它们转换为系列,最后将它们分配给 df 中的列来解决问题,如下面的代码所示:
preferred_list = []
least_preferred_list = []
for i in range(df_cli['CLIENT'].size):
preferred_list.append(preferred_day(i))
least_preferred_list.append(least_preferred_day(i))
prefered_day_s = pd.Series(preferred_list)
least_preferred_day_s = pd.Series(least_preferred_list)
df_cli['preferred_day'] = preferred_day_s
df_cli['least_preferred_day'] = least_preferred_day_s
这会产生我想要的结果,但是速度很慢。
我需要一种方法来消除使用 df.apply
时的 ValueError,或者另一种方法来更快地获得相同的结果。
首先,ValueError
的出现是因为 row
在传递给您的函数时是一个 Series
。这就是 apply
的工作方式(参见 the docs)。您似乎期望 row
是一个数字索引,这是不正确的。永远不需要从传递给 apply
的函数中引用原始数据框
您的第二个 groupby
走在了正确的轨道上,但是更快的方法是分两个阶段进行分组,如下所示:
def most_frequent_day(group):
''' Return most frequent DAY_EVENT occurrence for group. '''
return group['DAY_EVENT'].value_counts().apply(['max', 'idxmax'])
df.groupby('CLIENT').apply(most_frequent_day)
通过将 apply
与 groupby
结合使用,函数 most_frequent_day
会针对每个客户端调用一次,其中包含该客户端原始数据帧中的条目子集。对于每个子集,您可以简单地找到 DAY_EVENT 的最高频率。这returns结果:
DAY_EVENT max idxmax
CLIENT
Anne 1 MON
John 2 FRI
Jonas 1 SAT
Mary 2 SUN
我有以下 df,其中包含有关客户、活动日期和花费价值的信息: pandas dataframe
重现 df 的代码:
d = {'CLIENT': ['John', 'Jonas', 'Mary', 'Anne', 'John', 'Jonas', 'Mary','John', 'Mary'],'SPENT': [30, 400, 800, 90, 180, 560, 50, 200, 100],'DAY_EVENT': ['WED', 'SAT', 'SUN', 'MON', 'FRI', 'WED', 'THU', 'FRI', 'SUN']}
df = pd.DataFrame(data=d)
我首先使用以下聚合选项制作了一个 df.groupby
:
df_cli = df.groupby('CLIENT').agg({'SPENT': [np.size, np.sum, np.mean]}).reset_index()
这给我留下了这个: pandas groupby dataframe
我想确定我的客户最喜欢和最不喜欢的日子,但我不知道如何使它成为 groupby
函数的变量,所以我尝试了另一个 groupby
df:
df_cli_day = df.groupby(['CLIENT','DAY_EVENT']).agg({'SPENT':[np.size, np.sum, np.mean]}).reset_index(level=1)
然后我有这个: another pandas groupby dataframe
我尝试过定义函数,然后将它们应用于数据框,如下所示:
def preferred_day(row):
cli = df_cli['CLIENT'][row]
clidays = df_cli_day.loc[cli]
return clidays['DAY_EVENT'].max()
def least_preferred_day(row):
cli = df_cli['CLIENT'][row]
clidays = df_cli_day.loc[cli]
return clidays['DAY_EVENT'].min()
df_cli['preferred_day'] = df_cli.apply(lambda row: preferred_day(row), axis=1)
这引发了以下问题:
ValueError: ('cannot index with vector containing NA / NaN values', 'occurred at index 0')
由于我的函数在调用时起作用,所以我通过循环并将结果附加到列表,然后将它们转换为系列,最后将它们分配给 df 中的列来解决问题,如下面的代码所示:
preferred_list = []
least_preferred_list = []
for i in range(df_cli['CLIENT'].size):
preferred_list.append(preferred_day(i))
least_preferred_list.append(least_preferred_day(i))
prefered_day_s = pd.Series(preferred_list)
least_preferred_day_s = pd.Series(least_preferred_list)
df_cli['preferred_day'] = preferred_day_s
df_cli['least_preferred_day'] = least_preferred_day_s
这会产生我想要的结果,但是速度很慢。
我需要一种方法来消除使用 df.apply
时的 ValueError,或者另一种方法来更快地获得相同的结果。
首先,ValueError
的出现是因为 row
在传递给您的函数时是一个 Series
。这就是 apply
的工作方式(参见 the docs)。您似乎期望 row
是一个数字索引,这是不正确的。永远不需要从传递给 apply
您的第二个 groupby
走在了正确的轨道上,但是更快的方法是分两个阶段进行分组,如下所示:
def most_frequent_day(group):
''' Return most frequent DAY_EVENT occurrence for group. '''
return group['DAY_EVENT'].value_counts().apply(['max', 'idxmax'])
df.groupby('CLIENT').apply(most_frequent_day)
通过将 apply
与 groupby
结合使用,函数 most_frequent_day
会针对每个客户端调用一次,其中包含该客户端原始数据帧中的条目子集。对于每个子集,您可以简单地找到 DAY_EVENT 的最高频率。这returns结果:
DAY_EVENT max idxmax
CLIENT
Anne 1 MON
John 2 FRI
Jonas 1 SAT
Mary 2 SUN