【问题标题】:pandas apply function to each group (output is not really an aggregation)pandas 将函数应用于每个组(输出并不是真正的聚合)
【发布时间】:2020-11-09 23:22:20
【问题描述】:

我有一个时间序列列表(=pandas 数据帧),并希望为每个时间序列(设备的)计算矩阵配置文件。 一种选择是迭代所有设备——这似乎很慢。 第二种选择是按设备分组 - 并应用 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)

【问题讨论】:

标签: python pandas group-by


【解决方案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)

【讨论】:

    【解决方案2】:

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

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-09
      • 1970-01-01
      • 2019-05-09
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      相关资源
      最近更新 更多