2015-04-06 22 views
1

我已阅读此post,并怀疑我需要更好地理解索引。我想这样做np.ndenumerate,但(在这种特殊情况下)仅在第一三个维度,返回了一系列载体:像部分/选择np.ndenumerate?

x = np.linspace(0., 1., 4) 
y = np.linspace(0., 1., 5) 
z = np.linspace(0., 1., 2) 
X, Y, Z = np.meshgrid(x, y, z) # define a grid 
F = np.zeros(X.shape + (3,))  # a 3D vector field 
F = np.random.rand(5*4*2*3).reshape(5,4,2,3) # added this later just to give non-zero for testing 

thetas = np.linspace(0, 2.*np.pi, 21)[:-1] # drop the duplicate 
v = np.array([(np.cos(theta), np.sin(theta), 0.0) for theta in thetas]) 

for tup, vec in magical_enumerate(F, axis=(0,1,2)): # it's magic! (need correct expression) 
    F(tup) = np.cross(v, vec).sum(axis=0)  # sum over 20 vectors in v 

有没有办法做到这一点没有大量的循环或列表的解释?网格将很大,所以numpythony和速度值得赞赏。非连续维度(例如,轴=(0,2))呢?谢谢!

+0

你可以发布可运行代码,因为'magical_enumerate'是未定义的吗? – Divakar 2015-04-06 06:18:02

+0

嗨Divarak,这是我在SO中看到的那种速记,因为“我不知道该把什么放在这里,但这是我正在寻找的东西。”该代码仅仅是一个帮助澄清文本的例子。 – uhoh 2015-04-06 07:43:19

+0

我可能已经弄错了,但是你不能只是重塑'F',然后像'np.sum(np.cross(F.reshape(-1,F.shape [-1 ]),vec),1)'然后用这些值设置为'F'? – Divakar 2015-04-06 09:18:51

回答

3

np.ndindex可能会诀窍。它通过一组维度生成一个迭代器。

In [231]: F=np.zeros((2,3,3,3)) 

In [232]: for tup in np.ndindex(F.shape[:3]): 
    # vec = data[tup] etc 
    F[tup]=tup 
    .....:  

In [233]: F 
Out[233]: 
array([[[[ 0., 0., 0.], 
     [ 0., 0., 1.], 
     [ 0., 0., 2.]], 

     ... 
     [ 1., 2., 1.], 
     [ 1., 2., 2.]]]]) 

我建议看代码都ndenumeratendindexndindexmulti_index模式下使用最近的nditerndenumerate使用flat来遍历所有值。

我建议在其他所以你可以如何构建自己的multi_index迭代器模仿ndindex。在nditer上搜索可能会产生这些结果。

这不会给多个循环带来速度优势,因为您仍然在处理相同数量的最内部计算。

至于非顺序的尺寸,这同样ndindex将工作,但你必须使用它作为索引之前操纵tup

In [243]: for tup in np.ndindex((F.shape[0],F.shape[2])): 
    tup1=(tup[0],slice(None),tup[1]) 
    F[tup]=[tup[0],np.nan,tup[1]] 
    .....:  

np.apply_along_axisnp.apply_over_axes超过1个或多个生成的索引的其他例子在切割其他切片的同时,

+0

谢谢hpaulj!确实很有效!现在,如果我可以弄清楚如何用'[:]'而不是循环来做到这一点,速度会更快! – uhoh 2015-04-06 08:23:21