通过将元素与前一行中的元素进行比较而无需循环来筛选numpy数组

2024-09-28 18:51:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我对Python和NumPy非常陌生,已经花了几天时间寻找这个问题的答案。在

考虑下面的二维股票价格数组,第0列到第3列是开盘价、最高价、最低价和收盘价,每一行(0-6)是随后的几天。在

      O      H      L      C
0 | 43.97  43.97  43.75  43.94
1 | 43.97  44.25  43.97  44.25
2 | 44.22  44.38  44.12  44.34
3 | 44.41  44.84  44.38  44.81
4 | 44.97  45.09  44.47  45.00
5 | 44.97  45.06  44.72  44.97
6 | 44.97  45.12  44.91  44.97

对于本例,我将使用O、H、L或C来表示0-3列,而0、1或2表示O、H、L或C的行偏移量(向后)

H2表示后退两行的H列的值,C0表示当前行中C列的值。所以在第三排,H2等于44.25,C0等于44.81。在

我希望使用与逻辑语句C0>;H2或类似语句等效的条件从这种类型的数组中获取行。最后,我希望包含这样的多个比较,以返回数组行的子集。在

有没有可能在不遍历数组的情况下执行此操作?在


Tags: 答案numpy时间数组h2语句偏移量股票价格
1条回答
网友
1楼 · 发布于 2024-09-28 18:51:48

一般来说,你想要做的事情是(用你的例子“C0>;H2”):

values = data[2:][C[2:] > H[:-2]]

但是,您可以很容易地看到这是如何重复的。在

因此,最简单的方法是生成与其他数据长度相同的“H2”等新序列。执行此操作时,您需要某种方法来指示哪些值无效或插入有效值。在

处理这个问题的方法不止一种(例如,不同的边界条件、屏蔽数组等)。例如,您可以决定用最后一个有效值来扩展序列。在

现在,因为您有浮点数组,所以让我们将NaN插入缺失的位置。这样,任何比较都将返回False。在

在这种情况下,你可以做一些类似的事情:

^{pr2}$

或者更广泛地说:

def shift(data, amount):
    data = data[:-amount]
    pad = (amount, 0)
    return np.pad(data, pad, mode='constant', constant_values=(np.nan,))

这样你就可以直接比较了。E、 g.H[H > shift(H, 2)]


另外,正如DSM所提到的,请考虑为此使用pandas。总的来说,这会让你的生活更轻松,相应的表达方式是:

df[df.C > df.H.shift(2)]

详细说明

让我们把它分解一下。在

如果我们从序列x = [0, 1, 2, 3, 4, 5]开始,那么{}将给出{}

import numpy as np

x = np.arange(6)
x2 = x[2:]

但是,如果我们想将它与其他具有相同原始长度的序列进行比较,我们会遇到一个问题,因为x现在比另一个序列短两个项目。在

y = np.linspace(-2, -3, 6)

比较它们会产生一个值错误,因为它们的长度不一样:

In [4]: x2 > y
                                     -
ValueError                                Traceback (most recent call last)
<ipython-input-22-eec160476995> in <module>()
  > 1 x2 > y

ValueError: operands could not be broadcast together with shapes (4) (6)

此外,我们不想将新的“移位”x的第一个值与原始序列的第一个值进行比较。我们要比较“移位”序列的第一项和原始序列的第三项。在

为此,我们还需要对另一个序列进行切片。E、 g.y[2:]

In [5]: x2 > y[2:]
Out[5]: array([ True,  True,  True,  True], dtype=bool)

不过,这有点笨拙。我们需要知道x2被移动了多少才能正确使用它。在x2中插入新值要容易得多,这样我们就可以直接用它来索引了。在

在我的原始示例中,我使用np.pad在数组的开头插入NaNs。在

x2 = np.pad(x[:-2], (2, 0), mode='constant', constant_values=(np.nan,))  

在本例中,pad的必要参数有点尴尬。{11>如果您不想使用下面的内容:

x2 = np.hstack([2 * [np.nan], x[:-2]])

这两种方法的最大优点是我们有相同长度的数组,与np.nan的任何比较都是错误的。在

例如:

In [9]: x2
Out[9]: array([ nan,  nan,   0.,   1.,   2.,   3.])

In [10]: x2 > -np.inf
Out[10]: array([False, False,  True,  True,  True,  True], dtype=bool)

这样就很容易直接与y进行比较:

In [11]: y
Out[11]: array([-2. , -2.2, -2.4, -2.6, -2.8, -3. ])

In [12]: x2 > y
Out[12]: array([False, False,  True,  True,  True,  True], dtype=bool)

示例

作为一个更完整的例子:

import numpy as np

def main():
    data = np.array([[43.97, 43.97, 43.75, 43.94],
                     [43.97, 44.25, 43.97, 44.25],
                     [44.22, 44.38, 44.12, 44.34],
                     [44.41, 44.84, 44.38, 44.81],
                     [44.97, 45.09, 44.47, 45.00],
                     [44.97, 45.06, 44.72, 44.97],
                     [44.97, 45.12, 44.91, 44.97]])
    O, H, L, C = data.T

    values = data[C > shift(H, 2)]
    print values

def shift(data, amount):
    data = data[:-amount]
    pad = (amount, 0)
    return np.pad(data, pad, mode='constant', constant_values=(np.nan,))

main()

values则为:

[[ 44.22  44.38  44.12  44.34]
 [ 44.41  44.84  44.38  44.81]
 [ 44.97  45.09  44.47  45.  ]
 [ 44.97  45.06  44.72  44.97]]

为了展示一个pandas版本:

import pandas as pd

df = pd.DataFrame([[43.97, 43.97, 43.75, 43.94],
                   [43.97, 44.25, 43.97, 44.25],
                   [44.22, 44.38, 44.12, 44.34],
                   [44.41, 44.84, 44.38, 44.81],
                   [44.97, 45.09, 44.47, 45.00],
                   [44.97, 45.06, 44.72, 44.97],
                   [44.97, 45.12, 44.91, 44.97]],
                  columns=['O', 'H', 'L', 'C'])

values = df[df.C > df.H.shift(2)]
print values

结果是:

       O      H      L      C
2  44.22  44.38  44.12  44.34
3  44.41  44.84  44.38  44.81
4  44.97  45.09  44.47  45.00
5  44.97  45.06  44.72  44.97

相关问题 更多 >