我正在进行大量计算,将一个名为“因子”的 pandas 列与另一个名为“值”的列相乘,然后计算乘法的总和。
两列的长度通常约为 200 行。鉴于这是我在当前项目中进行了数千次的计算,我需要它尽可能快
代码的缩小版本如下所示(只有 4 行)
dict = {'factor': [0.25,0.25,0.25,0.25],
'value': [22000,25000,27000,35000] }
df = pd.DataFrame(dict, columns= ['factor', 'value'])
print((df['factor'] * df['value']).sum())
打印出27250。
有没有办法更快地获得相同的结果?
您可以使用
numpy
- 通过 values
将列转换为一维数组,然后 numpy.sum
:
np.random.seed(456)
d = {'factor': np.random.rand(200),
'value': np.random.randint(1000, size=200)}
df = pd.DataFrame(d, columns= ['factor', 'value'])
#print (df)
In [139]: %timeit ((df['factor'] * df['value']).sum())
245 µs ± 2.64 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [140]: %timeit (np.sum((df['factor'].values * df['value'].values)))
20.6 µs ± 328 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
numpy.nansum
来防止它:
np.random.seed(456)
d = {'factor': np.random.rand(200),
'value': np.random.randint(1000, size=200)}
df = pd.DataFrame(d, columns= ['factor', 'value'])
df['value'] = df['value'].mask(df['value'] > 700)
#print (df)
In [144]: %timeit ((df['factor'] * df['value']).sum())
235 µs ± 8.65 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [145]: %timeit (np.nansum((df['factor'].values * df['value'].values)))
33.3 µs ± 1.28 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
我重复使用 DF 柱或其 NP 对应物的实验,得到了与上面报道的不同的结果。我确实意识到它们很久以前就被共享了。看来现在的情况有所不同。这是我在一台配备 Intel Core i7-13700K 的空闲 Windows 11 计算机上使用 Pandas 2.2.2 和 Python 3.11.9 运行的程序。
df = pd.DataFrame()
x = "x"; y = "y"; z = "z"
df[x] = np.arange(100*1000*1000)
df[y] = np.arange(100*1000*1000)
n = 100
t1 = datetime.now()
for i in range(0, n):
pass
t2 = datetime.now(); print("Plain loop", t2-t1)
t1 = datetime.now()
for i in range(0, n):
a = (df[x]*df[y]).sum()
t2 = datetime.now(); print("DF columns", t2-t1)
t1 = datetime.now()
for i in range(0, n):
a = np.sum(df[x].values * df[y].values)
t2 = datetime.now(); print("NP arrays", t2-t1)
...这是输出:
Plain loop 0:00:00
DF columns 0:00:08.807886
NP arrays 0:00:11.704078
粗略地说,NP 数组方法大约慢 33%。经过多次手动运行后,结果仍然相同。我发现这令人惊讶,并想将这个新结果添加到这个旧序列中。