如何加速循环数组作为 pandas 计算的输入?

How tp speed up looping arrays as inputs for pandas calculation?

我有两个数组 xy。目标是迭代它们作为 pandas 计算的输入。

这是一个例子。 迭代每个 xy 并将计算结果附加到 res 列表很慢。

计算是得到a修改的每一列的指数,然后求和,乘以b。无论如何,这个计算可以用任何其他计算来代替。

import numpy as np
import pandas as pd

np.random.seed(0)
df = pd.DataFrame(np.random.randint(0,5,size=(5, 1)),columns=['data'])

x = np.linspace(1, 24, 4)
y = np.linspace(10, 1500, 5)

res = []

for a in x:
    for b in y:
        res.append(np.exp(-df/a).sum().values[0]*b)

res = np.array(res).reshape(4, 5)

预期输出:

array([[  11.67676844,  446.63639283,  881.59601721, 1316.5556416 ,
        1751.51526599],
       [  37.52524129, 1435.34047927, 2833.15571725, 4230.97095523,
        5628.78619321],
       [  42.79406912, 1636.87314392, 3230.95221871, 4825.0312935 ,
        6419.1103683 ],
       [  44.93972433, 1718.94445549, 3392.94918665, 5066.95391781,
        6740.95864897]])

你可以使用 numpy 广播:

res = np.array(res).reshape(4, 5)

print (res)
[[  11.67676844  446.63639283  881.59601721 1316.5556416  1751.51526599]
 [  37.52524129 1435.34047927 2833.15571725 4230.97095523 5628.78619321]
 [  42.79406912 1636.87314392 3230.95221871 4825.0312935  6419.1103683 ]
 [  44.93972433 1718.94445549 3392.94918665 5066.95391781 6740.95864897]]

res = np.exp(-df.to_numpy()/x).sum(axis=0)[:, None] * y
  
print (res)
[[  11.67676844  446.63639283  881.59601721 1316.5556416  1751.51526599]
 [  37.52524129 1435.34047927 2833.15571725 4230.97095523 5628.78619321]
 [  42.79406912 1636.87314392 3230.95221871 4825.0312935  6419.1103683 ]
 [  44.93972433 1718.94445549 3392.94918665 5066.95391781 6740.95864897]]

我想你想要的是:

z = -df['data'].to_numpy()
res = np.exp(z/x[:, None]).sum(axis=1)[:, None]*y

输出:

array([[  11.67676844,  446.63639283,  881.59601721, 1316.5556416 ,
        1751.51526599],
       [  37.52524129, 1435.34047927, 2833.15571725, 4230.97095523,
        5628.78619321],
       [  42.79406912, 1636.87314392, 3230.95221871, 4825.0312935 ,
        6419.1103683 ],
       [  44.93972433, 1718.94445549, 3392.94918665, 5066.95391781,
        6740.95864897]])