Python:数组中的条件元素

时间:2011-09-29 08:02:00

标签: python arrays conditional

来自完整的Python新手的问题。

我有一个列数组,我需要将某些值强制为零,具体取决于应用于另一个数组的条件语句。我找到了两个解决方案,它们都提供了正确答案。但是对于我通常需要的较大阵列(> 1E6元素)而言,它们都非常耗时 - 我也怀疑这是一种糟糕的编程技术。这两个版本是:

from numpy import zeros,abs,multiply,array,reshape

def testA(y, f, FC1, FC2):
    c = zeros((len(f),1))
    for n in xrange(len(f)):
        if abs(f[n,0]) >= FC1 and abs(f[n,0]) <= FC2:
            c[n,0] = 1.
    w = multiply(c,y)
    return w

def testB(y, f, FC1, FC2):
    z = [(abs(f[n,0])>=FC1 and abs(f[n,0])<=FC2) for n in xrange(len(f))]
    z = multiply(array(z,dtype=float).reshape(len(f),1), y)
    return z

输入数组是列数组,因为它匹配要完成的后处理。测试可以像:

>>> from numpy.random import normal as randn
>>> fs, N = 1.E3, 2**22
>>> f = fs/N*arange(N).reshape((N,1))
>>> x = randn(size=(N,1))
>>> w1 = testA(x,f,200.,550.)
>>> z1 = testB(x,f,200.,550.)

在我的笔记本电脑上 testA 需要18.7秒而 testB 需要19.3 - 两者都是N = 2 ** 22。在 testB 中,我还试图将“z = [None] * len(f)”包含在另一个帖子中建议的预分配中,但这并没有什么区别。

我有两个问题,我希望得到同样的答案:

  1. 这个问题的“正确”Python解决方案是什么?
  2. 我能做些什么来更快地得到答案吗?
  3. 我故意没有使用任何时间使用编译的Python - 我想先得到一些工作代码。希望还有一些东西,这是很好的Python风格。我希望能够在2秒左右的时间内获得N = 2 ** 22的执行时间。这个特殊的操作将被多次使用,因此执行时间很重要。

    如果问题很愚蠢,我会事先道歉 - 我无法在绝大多数不容易访问的Python文档或其他线程中找到答案。

2 个答案:

答案 0 :(得分:5)

使用bool数组访问数组y中的元素:

def testC(y, f, FC1, FC2):
    f2 = abs(f)
    idx = (f2>=FC1) & (f2<=FC2)
    y[~idx] = 0
    return y

答案 1 :(得分:0)

所有这些都比HYRY解决方案慢很多:

怎么样

( x[1] if FC1<=abs(x[0])<=FC2 else 0 for x in itertools.izip(f,x) )

如果你需要随机访问(非常慢)

[ x[1] if FC1<=abs(x[0])<=FC2 else 0 for x in itertools.izip(f,x) ]

或者您也可以使用地图

map(lambda x: x[1] if FC1<=abs(x[0])<=FC2 else 0 , itertools,izip(f,x))

或使用vectorize(比A和B快,但比C慢很多)

b1v = np.vectorize(lambda a,b: a if 200<=abs(b)<=550 else 0)
b1 = b1v(f,x)