简体   繁体   English

在numpy数组中没有for循环迭代

[英]Iterating without for loop in numpy array

I need to do logical iteration over numpy array, which's values depend on elements of other array. 我需要对numpy数组进行逻辑迭代,其值取决于其他数组的元素。 I've written code below for clarifying my problem. 我在下面写了代码来澄清我的问题。 Any suggestions to solve this problem without for loop? 有没有for循环解决这个问题的任何建议?

Code
a = np.array(['a', 'b', 'a', 'a', 'b', 'a'])
b = np.array([150, 154, 147, 126, 148, 125])
c = np.zeros_like(b)
c[0] = 150
for i in range(1, c.size):
    if a[i] == "b":
        c[i] = c[i-1]
    else:
        c[i] = b[i]

Here's an approach using a combination of np.maximum.accumulate and np.where to create stepped indices that are to be stopped at certain intervals and then simply indexing into b would give us the desired output. 这是一种使用np.maximum.accumulatenp.where组合的方法来创建以某些间隔停止的步进索引,然后简单地索引到b将为我们提供所需的输出。

Thus, an implementation would be - 因此,实施将是 -

mask = a!="b"
idx = np.maximum.accumulate(np.where(mask,np.arange(mask.size),0))
out = b[idx]

Sample step-by-step run - 逐步运行示例 -

In [656]: # Inputs 
     ...: a = np.array(['a', 'b', 'a', 'a', 'b', 'a'])
     ...: b = np.array([150, 154, 147, 126, 148, 125])
     ...: 

In [657]: mask = a!="b"

In [658]: mask
Out[658]: array([ True, False,  True,  True, False,  True], dtype=bool)

# Crux of the implmentation happens here :
In [696]: np.where(mask,np.arange(mask.size),0)
Out[696]: array([0, 0, 2, 3, 0, 5])

In [697]: np.maximum.accumulate(np.where(mask,np.arange(mask.size),0))
Out[697]: array([0, 0, 2, 3, 3, 5])# Stepped indices "intervaled" at masked places

In [698]: idx = np.maximum.accumulate(np.where(mask,np.arange(mask.size),0))

In [699]: b[idx]
Out[699]: array([150, 150, 147, 126, 126, 125])

You could use a more vectorized approach Like so: 您可以使用更加向量化的方法,如下所示:

np.where(a == "b", np.roll(c, 1), b)

np.where will take the elements from np.roll(c, 1) if the condition is True or it will take from b if the condition is False . np.where会从元件np.roll(c, 1)如果条件为True ,或者它会从b如果条件为False np.roll(c, 1) will "roll" forward all the elements of c by 1 so that each element refers to c[i-1] . np.roll(c, 1)将向前“滚动” c的所有元素,使每个元素引用c[i-1]

These type of operations are what make numpy so invaluable. 这些类型的操作使得numpy非常宝贵。 Looping should be avoided if possible. 如果可能,应该避免循环。

If you don't need to wrap around the margin there is a very simply solution: 如果您不需要包围边距,那么有一个非常简单的解决方案:

a = np.array(['a', 'b', 'a', 'a', 'b', 'a'])
b = np.array([150, 154, 147, 126, 148, 125])
c = b.copy()  #removes necessity of else case
c[a[:-1]=='b'] = c[a[1:]=='b']

or equally: 或同等地:

a = np.array(['a', 'b', 'a', 'a', 'b', 'a'])
b = np.array([150, 154, 147, 126, 148, 125])
c = b.copy()  #removes necessity of else case
mask = a == 'b'
c[mask[:-1]] = c[mask[1:]]

If you want to wrap around the margin ( a[0]=='b' ) then it gets a little more complicated, you either need to use roll or catch this case first with and if . 如果你想绕过边距( a[0]=='b' )那么它会变得有点复杂,你需要先使用roll或者先用if和catch来捕获这个案例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM