问题:如何选择给定条件的数组元素?
假设我有一个numpy数组x = [5, 2, 3, 1, 4, 5]
,y = ['f', 'o', 'o', 'b', 'a', 'r']
。我想选择与大于1小于5 的元素y
相对应的元素x
。
我试过了
x = array([5, 2, 3, 1, 4, 5])
y = array(['f','o','o','b','a','r'])
output = y[x > 1 & x < 5] # desired output is ['o','o','a']
但这不起作用。我该怎么做?
Suppose I have a numpy array x = [5, 2, 3, 1, 4, 5]
, y = ['f', 'o', 'o', 'b', 'a', 'r']
. I want to select the elements in y
corresponding to elements in x
that are greater than 1 and less than 5.
I tried
x = array([5, 2, 3, 1, 4, 5])
y = array(['f','o','o','b','a','r'])
output = y[x > 1 & x < 5] # desired output is ['o','o','a']
but this doesn’t work. How would I do this?
回答 0
如果添加括号,则表达式有效:
>>> y[(1 < x) & (x < 5)]
array(['o', 'o', 'a'],
dtype='|S1')
Your expression works if you add parentheses:
>>> y[(1 < x) & (x < 5)]
array(['o', 'o', 'a'],
dtype='|S1')
回答 1
IMO OP实际上并不需要np.bitwise_and()
(aka &
),但实际上是需要的,np.logical_and()
因为它们正在比较逻辑值,例如True
和False
-请参阅此SO 逻辑与按位比较,以了解区别。
>>> x = array([5, 2, 3, 1, 4, 5])
>>> y = array(['f','o','o','b','a','r'])
>>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
dtype='|S1')
同样的方法是np.all()
通过axis
适当设置参数。
>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
dtype='|S1')
通过数字:
>>> %timeit (a < b) & (b < c)
The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 1.15 µs per loop
>>> %timeit np.logical_and(a < b, b < c)
The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.17 µs per loop
>>> %timeit np.all([a < b, b < c], 0)
The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 5.06 µs per loop
所以使用np.all()
比较慢,但&
和logical_and
大致相同。
IMO OP does not actually want np.bitwise_and()
(aka &
) but actually wants np.logical_and()
because they are comparing logical values such as True
and False
– see this SO post on logical vs. bitwise to see the difference.
>>> x = array([5, 2, 3, 1, 4, 5])
>>> y = array(['f','o','o','b','a','r'])
>>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
dtype='|S1')
And equivalent way to do this is with np.all()
by setting the axis
argument appropriately.
>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
dtype='|S1')
by the numbers:
>>> %timeit (a < b) & (b < c)
The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 1.15 µs per loop
>>> %timeit np.logical_and(a < b, b < c)
The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.17 µs per loop
>>> %timeit np.all([a < b, b < c], 0)
The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 5.06 µs per loop
so using np.all()
is slower, but &
and logical_and
are about the same.
回答 2
在@JF Sebastian和@Mark Mikofski的答案中添加一个细节:
如果要获取相应的索引(而不是数组的实际值),则将执行以下代码:
为了满足多个(所有)条件:
select_indices = np.where( np.logical_and( x > 1, x < 5) )[0] # 1 < x <5
为了满足多个(或)条件:
select_indices = np.where( np.logical_or( x < 1, x > 5 ) )[0] # x <1 or x >5
Add one detail to @J.F. Sebastian’s and @Mark Mikofski’s answers:
If one wants to get the corresponding indices (rather than the actual values of array), the following code will do:
For satisfying multiple (all) conditions:
select_indices = np.where( np.logical_and( x > 1, x < 5) )[0] # 1 < x <5
For satisfying multiple (or) conditions:
select_indices = np.where( np.logical_or( x < 1, x > 5 ) )[0] # x <1 or x >5
回答 3
我喜欢np.vectorize
用于此类任务。考虑以下:
>>> # Arrays
>>> x = np.array([5, 2, 3, 1, 4, 5])
>>> y = np.array(['f','o','o','b','a','r'])
>>> # Function containing the constraints
>>> func = np.vectorize(lambda t: t>1 and t<5)
>>> # Call function on x
>>> y[func(x)]
>>> array(['o', 'o', 'a'], dtype='<U1')
好处是您可以在向量化函数中添加更多类型的约束。
希望能帮助到你。
I like to use np.vectorize
for such tasks. Consider the following:
>>> # Arrays
>>> x = np.array([5, 2, 3, 1, 4, 5])
>>> y = np.array(['f','o','o','b','a','r'])
>>> # Function containing the constraints
>>> func = np.vectorize(lambda t: t>1 and t<5)
>>> # Call function on x
>>> y[func(x)]
>>> array(['o', 'o', 'a'], dtype='<U1')
The advantage is you can add many more types of constraints in the vectorized function.
Hope it helps.
回答 4
其实我会这样做:
L1是满足条件1的元素的索引列表;(也许可以使用somelist.index(condition1)
或np.where(condition1)
获取L1。)
类似地,得到L2,即满足条件2的元素的列表。
然后您使用找到交集intersect(L1,L2)
。
如果您有多个要满足的条件,也可以找到多个列表的交集。
然后,您可以将索引应用于任何其他数组,例如x。
Actually I would do it this way:
L1 is the index list of elements satisfying condition 1;(maybe you can use somelist.index(condition1)
or np.where(condition1)
to get L1.)
Similarly, you get L2, a list of elements satisfying condition 2;
Then you find intersection using intersect(L1,L2)
.
You can also find intersection of multiple lists if you get multiple conditions to satisfy.
Then you can apply index in any other array, for example, x.
回答 5
对于2D阵列,您可以执行此操作。使用条件创建2D蒙版。根据数组,将条件掩码类型转换为int或float,然后将其与原始数组相乘。
In [8]: arr
Out[8]:
array([[ 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10.]])
In [9]: arr*(arr % 2 == 0).astype(np.int)
Out[9]:
array([[ 0., 2., 0., 4., 0.],
[ 6., 0., 8., 0., 10.]])
For 2D arrays, you can do this. Create a 2D mask using the condition. Typecast the condition mask to int or float, depending on the array, and multiply it with the original array.
In [8]: arr
Out[8]:
array([[ 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10.]])
In [9]: arr*(arr % 2 == 0).astype(np.int)
Out[9]:
array([[ 0., 2., 0., 4., 0.],
[ 6., 0., 8., 0., 10.]])