熊猫将功能应用于每个组(输出实际上不是聚合)

时间:2020-11-09 12:43:05

标签: python pandas group-by

我有一个时间序列列表(= pandas数据帧),并想为(设备的)每个时间序列计算matrixprofile。 一种选择是迭代所有设备-这似乎很慢。 第二种选择是按设备分组-并应用UDF。现在的问题是,UDF将返回1:1行,即不是每组一个标量值,而是将输出相同数量的行作为输入。

返回1:1(或至少是非标量值)后,是否仍可以某种方式对覆盖范围组的计算进行矢量化处理?

import pandas as pd
df = pd.DataFrame({
    'foo':[1,2,3], 'baz':[1.1, 0.5, 4], 'bar':[1,2,1]
})
display(df)

print('***************************')
# slow version retaining all the rows
for g in df.bar.unique():
    print(g)
    
    this_group = df[df.bar == g]
    # perform a UDF which needs to have all the values per group
    # i.e. for real I want to calculate the matrixprofile for each time-series of a device
    this_group['result'] = this_group.baz.apply(lambda x: 1)
    display(this_group)

print('***************************')

def my_non_scalar1_1_agg_function(x):
    display(pd.DataFrame(x))
    return x

# neatly vectorized application of a non_scalar function
# but this fails as:  Must produce aggregated value
df = df.groupby(['bar']).baz.agg(my_non_scalar1_1_agg_function)
display(df)

2 个答案:

答案 0 :(得分:1)

对于应用于不返回非标量值的每个不同组的非聚合函数,您需要跨组迭代方法,然后一起编译。

因此,考虑使用groupby(),后跟concat的列表或字典理解。确保方法输入并返回完整的数据框,序列或ndarray。

# LIST COMPREHENSION
df_list = [ myfunction(sub) for index, sub in df.groupby(['group_column']) ]
final_df = pd.concat(df_list)

# DICT COMPREHENSION
df_dict = { index: myfunction(sub) for index, sub in df.groupby(['group_column']) }
final_df = pd.concat(df_dict, ignore_index=True)

答案 1 :(得分:0)

实际上,这是一种使它以更快/更理想的方式工作的方法(另请参见注释中的链接)。也许还有更好的选择

import pandas as pd
df = pd.DataFrame({
    'foo':[1,2,3], 'baz':[1.1, 0.5, 4], 'bar':[1,2,1]
})
display(df)

grouped_df = df.groupby(['bar'])

altered = []
for index, subframe in grouped_df:
    display(subframe)
    subframe = subframe# obviously we need to apply the UDF here - not the idempotent operation (=doing nothing)
    altered.append(subframe)
    print (index)
    #print (subframe)
   
pd.concat(altered, ignore_index=True)
#pd.DataFrame(altered)
相关问题