在MATLAB中,很容易找到满足特定条件的值的索引:
>> a = [1,2,3,1,2,3,1,2,3];
>> find(a > 2) % find the indecies where this condition is true
[3, 6, 9] % (MATLAB uses 1-based indexing)
>> a(find(a > 2)) % get the values at those locations
[3, 3, 3]
在Python中执行此操作的最佳方法是什么?
到目前为止,我已经提出以下建议。要获得值:
>>> a = [1,2,3,1,2,3,1,2,3]
>>> [val for val in a if val > 2]
[3, 3, 3]
但如果我想要每个值的索引,那就更复杂了:
>>> a = [1,2,3,1,2,3,1,2,3]
>>> inds = [i for (i, val) in enumerate(a) if val > 2]
>>> inds
[2, 5, 8]
>>> [val for (i, val) in enumerate(a) if i in inds]
[3, 3, 3]
在Python中有更好的方法吗,特别是对于任意条件(不仅仅是'val> 2')?
我在NumPy中找到了与MATLAB“find”相同的函数,但我目前无法访问这些库。
答案 0 :(得分:80)
在numpy中你有where
:
>> import numpy as np
>> x = np.random.randint(0, 20, 10)
>> x
array([14, 13, 1, 15, 8, 0, 17, 11, 19, 13])
>> np.where(x > 10)
(array([0, 1, 3, 6, 7, 8, 9], dtype=int64),)
答案 1 :(得分:26)
您可以创建一个带有可调用参数的函数,该参数将在列表推导的条件部分中使用。然后,您可以使用lambda或其他函数对象来传递您的任意条件:
def indices(a, func):
return [i for (i, val) in enumerate(a) if func(val)]
a = [1, 2, 3, 1, 2, 3, 1, 2, 3]
inds = indices(a, lambda x: x > 2)
>>> inds
[2, 5, 8]
它更接近你的Matlab示例,而不必加载所有numpy。
答案 2 :(得分:7)
或使用numpy的非零功能:
import numpy as np
a = np.array([1,2,3,4,5])
inds = np.nonzero(a>2)
a[inds]
array([3, 4, 5])
答案 3 :(得分:5)
为什么不使用它:
[i for i in range(len(a)) if a[i] > 2]
或者对于任意条件,为您的条件定义一个函数f
并执行:
[i for i in range(len(a)) if f(a[i])]
答案 4 :(得分:4)
此应用程序更常用的document.getElementById('date_of_birth').addEventListener('change', function() {
console.log($('#date_of_birth').getDate());
});
例程是numpy.where()
;但是,我认为它的作用与numpy.nonzero()
相同。
numpy
要获取值,您可以存储索引并切片:
import numpy
a = numpy.array([1,2,3,4,5])
inds = numpy.where(a>2)
或者您可以将数组作为可选参数传递:
a[inds]
或多个数组:
numpy.where(a>2, a)
答案 5 :(得分:3)
要获取具有任意条件的值,可以将filter()
与lambda函数一起使用:
>>> a = [1,2,3,1,2,3,1,2,3]
>>> filter(lambda x: x > 2, a)
[3, 3, 3]
获取索引的一种可能方法是使用enumerate()
构建包含索引和值的元组,然后过滤:
>>> a = [1,2,3,1,2,3,1,2,3]
>>> aind = tuple(enumerate(a))
>>> print aind
((0, 1), (1, 2), (2, 3), (3, 1), (4, 2), (5, 3), (6, 1), (7, 2), (8, 3))
>>> filter(lambda x: x[1] > 2, aind)
((2, 3), (5, 3), (8, 3))
答案 6 :(得分:3)
我一直试图想出一个快速的方法来做这件事,这是我偶然发现的(使用numpy进行快速矢量比较):
a_bool = numpy.array(a) > 2
inds = [i for (i, val) in enumerate(a_bool) if val]
事实证明,这比以下快得多:
inds = [i for (i, val) in enumerate(a) if val > 2]
当在一个numpy数组中完成时,似乎Python比较快,而且/或者在检查真实而不是比较时更快地执行列表推导。
修改强>
我正在重新审视我的代码,我在一行中遇到了一个可能更少内存密集,更快,更简洁的方式:
inds = np.arange( len(a) )[ a < 2 ]
答案 7 :(得分:2)
我想我可能找到了一个快速而简单的替代品。 顺便说一下,我觉得np.where()函数不是很令人满意,从某种意义上说它包含了一个烦人的零元素行。
import matplotlib.mlab as mlab
a = np.random.randn(1,5)
print a
>> [[ 1.36406736 1.45217257 -0.06896245 0.98429727 -0.59281957]]
idx = mlab.find(a<0)
print idx
type(idx)
>> [2 4]
>> np.ndarray
最佳, 沓
答案 8 :(得分:0)
Matlab的查找代码有两个参数。约翰的代码解释了第一个参数但不是第二个参数。例如,如果你想知道索引在满足条件的位置:Mtlab的功能是:
find(x>2,1)
使用John的代码,你所要做的就是在indices函数的末尾添加一个[x],其中x是你正在寻找的索引号。
def indices(a, func):
return [i for (i, val) in enumerate(a) if func(val)]
a = [1, 2, 3, 1, 2, 3, 1, 2, 3]
inds = indices(a, lambda x: x > 2)[0] #[0] being the 2nd matlab argument
返回&gt;&gt;&gt; 2,第一个指标超过2。