我有一个返回字典的函数。该函数通过基于数据帧中的数组计算值来工作。
数据框大约有1000,000行,如下所示:
col1
row1 [2, 3, 44, 89.6,...]
row2 [10, 4, 33.3, 1.11,...]
row3 [3, 4, 3, 2.6, 5.9, 8, 10,...]
我的函数接受每一行中的每个数组,进行一些计算并根据这些计算返回一个字典。但是,它非常慢。有很多值得我筛选的数据,但是有没有办法我可以提高速度呢?
问题 数据帧很长。每个数组可以包含100多个值。范围从10-80。
我的代码如下:
list1 = []
for i in df.itertuples():
list1.append(list(function(i.data).values()))
这里的想法是我遍历'df'中的每一行,将我的函数应用于'data'列,并将结果附加到列表'list1'。
功能介绍
我的函数计算了一些非常基本的东西。它接受一个数组作为参数,并根据该数组计算东西,例如多长时间,数组中的平均值,数组的最小值和最大值。我计算8个值并将它们存储在字典中。函数的最后一件事是查看这些计算出的值,并以布尔值的形式向字典添加最终键。
答案 0 :(得分:0)
就像我在评论中说的那样,如果您的函数很昂贵(减少每一行是代码的耗时部分),那么第一步是使用multiprocessing
,因为它很容易测试。
您可以尝试以下方法:
import time
from multiprocessing import Pool
def f(x):
time.sleep(10*10**-6) # Faking complex computation
return x
def seq_test(input_array):
return list(map(f, input_array))
def par_test(input_array):
pool = Pool(8) # "nproc --all" or "sysctl -n hw.ncpu" on osx
return pool.map(f, input_array)
def run_test(test_function):
test_size = 10*10**4
test_input = [i for i in range(test_size)]
t0 = time.time()
result = test_function(test_input)
t1 = time.time()
print(f"{test_function.__name__}: {t1-t0:.3f}s")
run_test(seq_test)
run_test(par_test)
在我的计算机上,并行版本的运行速度大约快了7倍(非常接近我们希望的8倍):
seq_test: 2.131s
par_test: 0.300s
如果这还不够的话,下一步是用另一种语言编写函数f
,这里看起来更简单的是使用Cython。但是要进行讨论,我们需要查看您的函数内部是什么。
答案 1 :(得分:0)
我建议您更改数据格式,例如:
print (df)
col1
row1 [2, 3, 44, 89.6]
row2 [10, 4, 33.3, 1.11]
row3 [3, 4, 3, 2.6, 5.9, 8, 10]
from itertools import chain
df = pd.DataFrame({
'idx' : df.index.repeat(df['col1'].str.len()),
'col1' : list(chain.from_iterable(df['col1'].tolist()))
})
print (df)
idx col1
0 row1 2.00
1 row1 3.00
2 row1 44.00
3 row1 89.60
4 row2 10.00
5 row2 4.00
6 row2 33.30
7 row2 1.11
8 row3 3.00
9 row3 4.00
10 row3 3.00
11 row3 2.60
12 row3 5.90
13 row3 8.00
14 row3 10.00
然后汇总您的数据:
df1 = df.groupby('idx')['col1'].agg(['sum','mean','max','min'])
print (df1)
sum mean max min
idx
row1 138.60 34.650000 89.6 2.00
row2 48.41 12.102500 33.3 1.11
row3 36.50 5.214286 10.0 2.60