2012-02-09 80 views
1

我在寻找一种高效优雅的方式来做到这一点。我希望这个例子能够解释我的担忧。numpy slice assignment

我们已经有了一个np.array这样的:

omega = np.array([1.03415121504, 1.29595060284, 1.55774999064, 1.81954937844, 
        ... 
        2.08134876623, 2.37359445321, -2.11179506541, -1.84999567761]) 

,现在我想操纵它,就像

omega[omega < 0.0] = omega + 2 * np.pi 
omega[omega >= 2 * np.pi] = omega - 2 * np.pi 

第二条语句可以覆盖拳头声明的计算值,然后有一个十字路口。我发现np.piecewise,但是这不提供这样的行为。

我该如何达到这个效率?

的corrent行为是这样的(但很效率不高/不雅):

tmp = [] 
for o in omega: 
    if o < 0.0: 
     tmp.append(o + 2 * np.pi) 
    elif o >= (2 * np.pi): 
     tmp.append(o - 2 * np.pi) 
    else: 
     tmp.append(o) 
omega = np.array(tmp) 

因此有人提出用numpy的的nditer用于上述目的的经历? (尤其是性能/效率)

+1

你是否意识到欧米加奥米加= 0 + 2 * np.pi'有点奇怪?你可能意指'欧米茄[欧米茄<0.0] + = 2 * np.pi'。 (第一种形式为'omega'的所有元素添加'2 * np.pi',然后使用这个新数组中的第一个条目作为'omega'的第一个否定条目的值 - 值变得很奇怪) – 2012-02-09 15:34:29

+0

@SvenMarnach哇,当你用2d或3d数组做它时,它会给出一个错误,“数组不能广播以纠正形状”,当你做omega [:] = wrong_size_array时,它会给出一个错误,所以它有点奇怪的是,1d布尔索引案例不检查不匹配。 – 2012-02-09 18:00:07

+0

@Bago:这种行为实际上是记录在案的。它有时是有用的,但对于更高维度没有有用的概括。 – 2012-02-09 18:11:01

回答

3

你可以尝试使用np.selecthttp://docs.scipy.org/doc/numpy/reference/generated/numpy.select.html

condlist = [omega < 0.0, omega >= 2.0*np.pi] 
choicelist = [omega + 2.0*np.pi, omega - 2.0*np.pi] 
omega = np.select(condlist,choicelist,default=omega) 
+0

这很方便,虽然它的缺点是做了比必要的更多的计算。如果这不是瓶颈,但它可以很好地工作。 – DSM 2012-02-09 15:42:03

2

第二条语句可能会覆盖第一条语句的计算值。

这是没有办法发生的。如果是前小于零,添加2*pi绝不会让它大于或等于2*pi

无论如何,一个简单的方法来实现你想要的可能是什么

omega %= 2 * np.pi 
+0

我的例子不够详尽,我有几个这样的结构,有两个以上的表达式。有没有一种通用的方法来避免带切片的for-loop,没有竞态条件?你的代码工作(谢谢!),但上面的例子产生错误的值。 – Themerius 2012-02-09 15:31:21

2

我建议做对指数的计算:

i = omega < 0.0 
omega[i] += 2*np.pi 
i = (~i) & (omega >= 2 * np.pi) 
omega[i] -= 2*np.pi 

第三行中的按位逻辑操作可确保不会使用两次索引。从你给出的例子来看,Sven Marnach的模解答更有效率。如果你有更复杂的用例,你应该更新你的问题。