【问题标题】:How to get the number of continuous increase data point in Pandas dataframe如何获取 Pandas 数据框中连续增加数据点的数量
【发布时间】:2015-03-02 22:01:00
【问题描述】:

提前感谢您的帮助! 我有一个数据框。比如说,对于colume incr,如果0 1 1 1 -1 0 1 1 ....的数字,我想解析列表并获取每个数据点,数据列表增加了多少次(或者更确切地说不是减少);该点的减少会将当前数据点的输出重置为零。例如对于列表(代码中名为 output['inc_adj'] ) 0 1 1 1 -1 0 1 -1 我应该在代码中命名为 output['cont_inc'] 1 2 3 4 0 1 2 0

我写了以下代码,但是效率很低,请问有什么建议可以显着提高效率吗?在两个循环中,我似乎一直在重新加载 CPU 中的缓存(如果我的感觉是正确的),但我目前找不到更好的解决方案。

output['cont_inc']=0;
for i in xrange(1,output['inc_adj'].count()):
    j=i;
    while(output['inc_adj'][j] != -1):
          #for both increase or unchanged
        output['cont_inc'][i]+=1;
        j-=1

提前致谢!

【问题讨论】:

    标签: python optimization pandas while-loop cpu-cache


    【解决方案1】:

    如果内存允许,我建议构建一个包含所有相邻值的列表以进行比较(在我的示例中使用 zip),并将结果附加到新列表中,重新分配完成后将整个结果列表返回到DataFrame。

    虽然听起来很奇怪,但实际上它通过消除一些常量 DataFrame 索引/值查找的开销来稍微提高性能:

    import pandas as pd
    import random
    
    # random DataFrame with values from -1 to 2
    df = pd.DataFrame([random.randint(-1, 2) for _ in xrange(999)], columns=['inc_adj'])
    df['cont_inc'] = 0
    
    def calc_inc(df):
        inc = [1]
        # I use zip to PREPARE the adjacent values
        for i, n in enumerate(zip(df['inc_adj'][1:], df['inc_adj'][:-1]), 0):
            if n[0] >= n[1]:
                inc.append(inc[i]+1)
                continue
            inc.append(0)
        df['cont_inc'] = inc
    

    calc_inc(df)
    
    df.head()
       inc_adj  cont_inc
    0        0         1
    1        0         2
    2        1         3
    3       -1         0
    4        0         1
    
    %timeit calc_inc(df)
    1000 loops, best of 3: 696 µs per loop
    

    作为比较,使用索引和/或查找和就地分配,类似的编码逻辑:

    def calc_inc_using_ix(df):
        for idx, row in df.iterrows():
            try:
                if row['inc_adj'] >= df['inc_adj'][idx-1]:
                    row['cont_inc'] = df['cont_inc'][idx-1] + 1
                    continue
                row['cont_inc'] = 0
            except KeyError:
                row['cont_inc'] = 1
    

    calc_inc_using_ix(df)
    
    df.head()
       inc_adj  cont_inc
    0        0         1
    1        1         2
    2        1         3
    3        0         0
    4        2         1
    
    %timeit calc_inc_using_ix(df)
    10 loops, best of 3: 58.5 ms per loop
    

    也就是说,我也对任何其他可以进一步提高性能的解决方案感兴趣,并且总是愿意学习。

    【讨论】:

    • 非常感谢您的帮助。它以更好的性能解决了我的问题。我可能会将整个列表分成几部分,以适应大型数据集的内存。非常感谢您的帮助!
    • @Tsigalko2003,没问题,我也很想看看性能和效率:)
    猜你喜欢
    • 2020-12-03
    • 2023-03-10
    • 1970-01-01
    • 2018-05-26
    • 2021-11-09
    • 2015-01-02
    • 2022-01-08
    • 2018-01-11
    • 1970-01-01
    相关资源
    最近更新 更多