1

我正在将 scipy.stats 中的调和平均值应用于 Pandas pivot_table 中的 aggfunc 参数,但它比简单平均值要慢几个数量级。

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

我需要使用调和平均值,但这需要大量的处理时间。

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

谢谢

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)

4

1 回答 1

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)
于 2019-05-24T13:18:26.523 回答