提高熊猫的谐波平均效率

时间:2019-05-24 12:36:40

标签: python python-3.x pandas numpy scipy

我正在使用scipy.stats中的谐波平均值作为熊猫数据透视表中的aggfunc参数,但是它比简单的平均值慢了几个数量级。

我想知道这是否是例外行为,或者有一种方法可以使此计算效率更高,因为我需要进行数千次此计算。

我需要使用谐波均值,但这需要花费大量的处理时间。

我尝试从Python 3.6的统计数据中使用谐和函数,但开销仍然相同。

谢谢

import numpy as np
import pandas as pd
import statistics

data = pd.DataFrame({'value1':np.random.randint(1000,size=200000),
                     'value2':np.random.randint(24,size=200000),
                     'value3':np.random.rand(200000)+1,
                     'value4':np.random.randint(100000,size=200000)})

%timeit result = pd.pivot_table(data,index='value1',columns='value2',values='value3',aggfunc=hmean)
1.74 s ± 24.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit result = pd.pivot_table(data,index='value1',columns='value2',values='value3',aggfunc=lambda x: statistics.harmonic_mean(list(x)))
1.9 s ± 26.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit result = pd.pivot_table(data,index='value1',columns='value2',values='value3',aggfunc=np.mean)
37.4 ms ± 938 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

#Single run for both functions
%timeit hmean(data.value3[:100])
155 µs ± 3.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit np.mean(data.value3[:100])
138 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

1 个答案:

答案 0 :(得分:2)

我建议使用 multiprocessing.Pool ,下面的代码已经过2000万条记录的测试,比原始代码快3倍,请尝试一下,请确保代码仍然需要更多改进回答有关statistics.harmonic_mean性能缓慢的特定问题。 注意:对于大于100 M的记录,您可以获得更好的结果。

import time
import numpy as np
import pandas as pd
import statistics
import multiprocessing

data = pd.DataFrame({'value1':np.random.randint(1000,size=20000000),
                     'value2':np.random.randint(24,size=20000000),
                     'value3':np.random.rand(20000000)+1,
                     'value4':np.random.randint(100000,size=20000000)})


def chunk_pivot(data):
    result = pd.pivot_table(data,index='value1',columns='value2',values='value3',aggfunc=lambda x: statistics.harmonic_mean(list(x)))
    return result


DataFrameDict=[]
for i in range(4):
    print(i*250,i*250+250)
    DataFrameDict.append(data[:][data.value1.between(i*250,i*250+249)])

def parallel_pivot(prcsr):
# 6 is a number of processes I've tested
    p = multiprocessing.Pool(prcsr)
    out_df=[]
    for result in p.imap(chunk_pivot, DataFrameDict):
        #print (result)
        out_df.append(result)
    return out_df

start =time.time()
dict_pivot=parallel_pivot(6)
multiprocessing_result=pd.concat(dict_pivot,axis=0)
#singleprocessing_result = pd.pivot_table(data,index='value1',columns='value2',values='value3',aggfunc=lambda x: statistics.harmonic_mean(list(x)))
end = time.time()
print(end-start)