我怎样才能用 Numpy 加快速度?

How can I speed this up with Numpy?

所以我已经为此苦苦挣扎了 2 天,终于设法让它工作了,但我想知道是否有办法加快速度,因为我有大量数据要处理。

这里的目标是我的数据帧的每一行每一列,我想计算一个增量和(elt(n-1)+ elt(n)),然后取绝对值并比较局部绝对值到前一个,以便在我专栏的最后一个元素处获得最大值。我虽然简单地使用滚动总和或简单的列总和会起作用,但不知何故我做不到。这些最大值是在 2000 行上滚动计算的。 (所以对于 elt n,我从第 n 行直到第 n+2000 行,等等)。最后,我将得到一个长度为原始数据帧减去 2000 个元素的数据帧。

关于速度,完成所有 4 列大约需要 1 分钟(这是针对仅包含大约 5000 个元素的相对较小的文件,其中大部分会大 4 倍)。

理想情况下,我想大幅加快“for pulse in range(2000):”循环中的内容,但如果我能加快整个代码也很好。 我不确定我该如何使用列表理解。我检查了 numpy accumulate() 函数或 rolling() 但它没有给我想要的东西。

edit1:缩进。

edit2:这里是第一列的前 10 行输入和输出的示例(以减少这里的繁忙)。问题是您至少需要 2000 行输入才能获得结果中的第一项,因此不确定它在这里是否真的有用。

   Input : 

   -2.1477511E-12
   2.0970403E-12
   2.0731764E-12
   1.7241669E-12
   1.2260080E-12
   7.3381503E-13
   8.2330457E-13
   -9.2472616E-13
   -1.1275693E-12
   -1.3184806E-12


   Output: 
   2.25436311E-10
   2.28640040E-10
   2.27405083E-10
   2.25331907E-10
   2.23607740E-10
   2.22381732E-10
   2.21647917E-10
   2.20824612E-10
   2.21749338E-10
   2.22876908E-10

这是我的代码:

    ys_integral_check_reduced = ys_integral_check[['A', 'B', 'C', 'D']]
    for col in ys_integral_check_reduced.columns:
            pulse=0
            i=0
            while (ys_integral_check_reduced.loc[i+1999,col] != 0 and i<len(ys_integral_check_reduced)-2000):
                cur = 0
                max = 0
                for pulse in range(2000):
                    cur = cur + ys_integral_check_reduced.loc[i+pulse, col]
                    if abs(cur) > max:
                        max = abs(cur)
                    pulse = pulse+1
                ys_integral_check_reduced_final.loc[i, col] = max
                i = i+1
     print(ys_integral_check_reduced_final)

如果我没理解错的话,我创建了一个玩具示例(WINDOW 大小为 3)。

import pandas as pd

WINDOW = 3

ys_integral_check = pd.DataFrame({'A':[1, 2, -5, -6, 1, -10, -1, -10, 7, 4, 5, 6],
                                  'B':[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]})
ys_integral_check['C'] = -ys_integral_check['B']

看起来像这样:

     A   B   C
0    1   1  -1
1    2   2  -2
2   -5   3  -3
3   -6   4  -4
4    1   5  -5
5  -10   6  -6
6   -1   7  -7
7  -10   8  -8
8    7   9  -9
9    4  10 -10
10   5  11 -11
11   6  12 -12

您的解决方案给出:

ys_integral_check_reduced_final = pd.DataFrame(columns=['A', 'B', 'C'])
ys_integral_check_reduced = ys_integral_check[['A', 'B', 'C']]

for col in ys_integral_check_reduced.columns:
        pulse=0
        i=0
        while (ys_integral_check_reduced.loc[i+WINDOW-1,col] != 0 and i<len(ys_integral_check_reduced)-WINDOW):
            cur = 0
            max = 0
            for pulse in range(WINDOW):
                cur = cur + ys_integral_check_reduced.loc[i+pulse, col]
                if abs(cur) > max:
                    max = abs(cur)
                pulse = pulse+1
            ys_integral_check_reduced_final.loc[i, col] = max
            i = i+1
print(ys_integral_check_reduced_final)
    A   B   C
0   3   6   6
1   9   9   9
2  11  12  12
3  15  15  15
4  10  18  18
5  21  21  21
6  11  24  24
7  10  27  27
8  16  30  30

这是使用 Pandas 和 Rolling.apply() 的变体:

ys_integral_check_reduced_final = ys_integral_check[['A', 'B', 'C']].rolling(WINDOW).apply(lambda w: w.cumsum().abs().max()).dropna().reset_index(drop=True)

给出:

      A     B     C
0   3.0   6.0   6.0
1   9.0   9.0   9.0
2  11.0  12.0  12.0
3  15.0  15.0  15.0
4  10.0  18.0  18.0
5  21.0  21.0  21.0
6  11.0  24.0  24.0
7  10.0  27.0  27.0
8  16.0  30.0  30.0
9  15.0  33.0  33.0

有一个额外的行,因为我相信你的解决方案在最后跳过了一个可能的 window。

我在具有 100'000 行和 3 列且 window 大小为 2000 的随机 DataFrame 上对其进行了测试,处理时间为 18 秒:

import time
import numpy as np

WINDOW = 2000
DF_SIZE = 100000

test_df = pd.DataFrame(np.random.random((DF_SIZE, 3)), columns=list('ABC'))

t0 = time.time()

test_df.rolling(WINDOW).apply(lambda w: w.cumsum().abs().max()).dropna().reset_index(drop=True)

t1 = time.time()

print(t1-t0) # 18.102170944213867