【问题标题】:pandas: fast custom aggregationpandas:快速自定义聚合
【发布时间】:2021-04-26 21:16:47
【问题描述】:

我有一个必须重新采样的时间索引数据:

interval = pd.Timedelta(1/8, "s")
resampled_df = df[["T", "N"]].resample(interval).max()

它工作得非常快,但我需要自定义聚合函数(极端)而不是max

def extreme_agg(array_like):
    # return max or min - which absolute value is greater
    return max(array_like.max(), array_like.min(), key=abs)

interval = pd.Timedelta(1/8, "s")
resampled_df = df[["T", "N"]].resample(interval).apply(extreme_agg)

我也试过了

resampled_df = df[["T", "N"]].resample(interval).agg(extreme_agg)

但是这两种方式都非常缓慢。 你知道如何让它更快吗?

或者有没有我的extreme_agg 的快速等价物?

【问题讨论】:

    标签: pandas numpy aggregation


    【解决方案1】:

    您可以使用更改this function 处理DataFrame.xs 选择的最小值和最大值,首先是minmax 的聚合值:

    np.random.seed(2021)
    
    N = 10000
    df = pd.DataFrame({'T':np.random.randint(100, size=N),
                       'N':np.random.randint(100, size=N)},
                      index=pd.timedelta_range(0, freq='100ms', periods=N)).sub(50)
    # print (df)
        
    
    def npwhere(df):
        interval = pd.Timedelta(1/8, "s")
        resampled_df = df[["T", "N"]].resample(interval).agg(['max','min'])
        amax = resampled_df.xs('max', axis=1, level=1)
        amin = resampled_df.xs('min', axis=1, level=1)
        return pd.DataFrame(np.where(-amin > amax, amin, amax), 
                                    index=resampled_df.index,
                                    columns=['T','N'])
    
    resampled_df = npwhere(df)
    print (resampled_df.head(10))
    
    def extreme_agg(array_like):
        # return max or min - which absolute value is greater
        return max(array_like.max(), array_like.min(), key=abs)
    
    interval = pd.Timedelta(1/8, "s")
    resampled_df1 = df[["T", "N"]].resample(interval).agg(extreme_agg)
    print (resampled_df1.head(10))
    
    print (resampled_df.equals(resampled_df1))
    True
    

    In [206]: %timeit npwhere(df)
    12.4 ms ± 46.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    In [207]: %timeit df[["T", "N"]].resample(interval).agg(lambda x: max(x, key = abs))
    306 ms ± 4.47 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    In [208]: %timeit df[["T", "N"]].resample(interval).agg(extreme_agg)
    2.29 s ± 14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    【讨论】:

    • npwhere 解决方案完美运行。尽管重采样进行了两次,但它使用内置的快速方法 - 它更快!谢谢
    【解决方案2】:

    这应该可行:

    resampled_df = df[["T", "N"]].resample(interval).agg(lambda x: max(x, key = abs))
    

    【讨论】:

    • 检查,它给出了相同的答案,它只是在两者都存在时更喜欢负值而不是正值 - 即 max([-23, 23], key = abs)-23 而它是 23 对于 OP 和你。
    • 嗯,明白了。那么好吧。
    • @jezrael 实际上测试更多 max 更喜欢第一个值,而您的 absmaxND 只喜欢正值 - 这会给您(和操作的)算法带来正偏差。
    • 有趣的研究 ;)
    猜你喜欢
    • 2019-11-05
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 2015-07-04
    • 2017-08-04
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    相关资源
    最近更新 更多