我试图概括一些Python代码来操作任意维度的数组。这些操作应用于数组中的每个向量。因此对于1D阵列,只有一个操作,对于2-D阵列,它将是行和列(线性,因此顺序无关紧要)。例如,1D数组(a)很简单:
b = operation(a)
其中'operation'期待一维数组。对于2D阵列,操作可以按
进行for ii in range(0,a.shape[0]):
b[ii,:] = operation(a[ii,:])
for jj in range(0,b.shape[1]):
c[:,ii] = operation(b[:,ii])
我想在不需要事先了解数组维度的情况下进行此通用,并且没有为每个可能维度设置大量if / elif语句。 对于1或2维通用的解决方案是可以的,但是优选完全通用的解决方案。实际上,我认为不需要任何高于2的维度,但如果我能看到一个通用的例子,我会学到一些东西!
额外信息: 我有一个matlab代码,使用单元格做类似的事情,但我不完全理解它是如何工作的。在这个例子中,每个向量都被重新排列(基本上与numpy.fft中的fftshift相同)。不确定这是否有帮助,但它可以在任意维度的数组上运行。
function aout=foldfft(ain)
nd = ndims(ain);
for k = 1:nd
nx = size(ain,k);
kx = floor(nx/2);
idx{k} = [kx:nx 1:kx-1];
end
aout = ain(idx{:});
答案 0 :(得分:1)
如果您正在寻找一种编程方式来将k-th
维度编入索引n
- 维数组,那么numpy.take
可能会对您有所帮助。
下面以foldfft
的实现为例:
In[1]:
import numpy as np
def foldfft(ain):
result = ain
nd = len(ain.shape)
for k in range(nd):
nx = ain.shape[k]
kx = (nx+1)//2
shifted_index = list(range(kx,nx)) + list(range(kx))
result = np.take(result, shifted_index, k)
return result
a = np.indices([3,3])
print("Shape of a = ", a.shape)
print("\nStarting array:\n\n", a)
print("\nFolded array:\n\n", foldfft(a))
Out[1]:
Shape of a = (2, 3, 3)
Starting array:
[[[0 0 0]
[1 1 1]
[2 2 2]]
[[0 1 2]
[0 1 2]
[0 1 2]]]
Folded array:
[[[2 0 1]
[2 0 1]
[2 0 1]]
[[2 2 2]
[0 0 0]
[1 1 1]]]
答案 1 :(得分:1)
您可以使用numpy.ndarray.flat,它允许您在n维numpy数组上线性迭代。您的代码应该如下所示:
{{1}}
答案 2 :(得分:1)
在Octave中,您的MATLAB代码执行:
(n[i]<n[smallest])
然后它使用octave:19> size(ain)
ans =
2 3 4
octave:20> idx
idx =
{
[1,1] =
1 2
[1,2] =
1 2 3
[1,3] =
2 3 4 1
}
单元格数组来索引idx
。通过这些尺寸,它可以“滚动”4号尺寸。
对于5和6,索引列表将是:
ain
2 3 4 5 1
3 4 5 6 1 2
中的等价物是:
numpy
除了基于0的索引之外,我还使用In [161]: ain=np.arange(2*3*4).reshape(2,3,4)
In [162]: idx=np.ix_([0,1],[0,1,2],[1,2,3,0])
In [163]: idx
Out[163]:
(array([[[0]],
[[1]]]), array([[[0],
[1],
[2]]]), array([[[1, 2, 3, 0]]]))
In [164]: ain[idx]
Out[164]:
array([[[ 1, 2, 3, 0],
[ 5, 6, 7, 4],
[ 9, 10, 11, 8]],
[[13, 14, 15, 12],
[17, 18, 19, 16],
[21, 22, 23, 20]]])
来重构索引。 MATLAB和np.ix_
使用不同的语法来索引值块。
下一步是使用代码构建numpy
,这是一种直接的翻译。
我可以使用[0,1],[0,1,2],[1,2,3,0]
作为将2个切片转换为索引数组的捷径:
np.r_
并通过In [201]: idx=[]
In [202]: for nx in ain.shape:
kx = int(np.floor(nx/2.))
kx = kx-1;
idx.append(np.r_[kx:nx, 0:kx])
.....:
In [203]: idx
Out[203]: [array([0, 1]), array([0, 1, 2]), array([1, 2, 3, 0])]
传递它以生成适当的索引元组:
np.ix_
在这种情况下,如果2个维度没有滚动任何内容,In [204]: ain[np.ix_(*idx)]
Out[204]:
array([[[ 1, 2, 3, 0],
[ 5, 6, 7, 4],
[ 9, 10, 11, 8]],
[[13, 14, 15, 12],
[17, 18, 19, 16],
[21, 22, 23, 20]]])
可以替换它们:
slice(None)
======================
In [210]: idx=(slice(None),slice(None),[1,2,3,0])
In [211]: ain[idx]
:
np.roll
indexes = concatenate((arange(n - shift, n), arange(n - shift)))
res = a.take(indexes, axis)
是另一个构造索引数组的函数(并将其转换为元组以进行索引)。
答案 3 :(得分:0)
上述人员提供了多种适当的解决方案。为了完整起见,这是我的最终解决方案。在这个玩具示例中,对于3维的情况,函数'ops'用1替换向量的第一个和最后一个元素。
import numpy as np
def ops(s):
s[0]=1
s[-1]=1
return s
a = np.random.rand(4,4,3)
print '------'
print 'Array a'
print a
print '------'
for ii in np.arange(a.ndim):
a = np.apply_along_axis(ops,ii,a)
print '------'
print ' Axis',str(ii)
print a
print '------'
print ' '
得到的3D数组在'border'上的每个元素中都有1,数组中间的数字不变。这当然是一个玩具的例子;但是ops可以是在1D向量上运行的任意函数。
展平矢量也会起作用;我之所以选择不去追求,只是因为记账更加困难,而且apply_along_axis是最简单的方法。