【发布时间】:2012-07-13 09:55:06
【问题描述】:
我正在尝试将我构建的一些 Matlab 库移动到 python 环境中。到目前为止,我面临的最大问题是基于索引规范的数组动态分配。例如,使用 Matlab,输入以下内容:
x = [1 2];
x(5) = 3;
会导致:
x = [ 1 2 0 0 3]
换句话说,我事先不知道 (x) 的大小,也不知道它的内容。必须根据我提供的索引动态定义数组。
在 python 中,尝试以下操作:
from numpy import *
x = array([1,2])
x[4] = 3
会导致以下错误:IndexError: index out of bounds。解决方法是在循环中递增数组,然后将所需的值分配为:
from numpy import *
x = array([1,2])
idx = 4
for i in range(size(x),idx+1):
x = append(x,0)
x[idx] = 3
print x
它可以工作,但它不是很方便,并且对于 n 维数组可能会变得非常麻烦。我虽然关于子类化 ndarray 来实现我的目标,但我不确定它是否会工作。有人知道更好的方法吗?
感谢您的快速回复。我不知道 setitem 方法(我对 Python 还很陌生)。我只是简单地覆盖了 ndarray 类如下:
import numpy as np
class marray(np.ndarray):
def __setitem__(self, key, value):
# Array properties
nDim = np.ndim(self)
dims = list(np.shape(self))
# Requested Index
if type(key)==int: key=key,
nDim_rq = len(key)
dims_rq = list(key)
for i in range(nDim_rq): dims_rq[i]+=1
# Provided indices match current array number of dimensions
if nDim_rq==nDim:
# Define new dimensions
newdims = []
for iDim in range(nDim):
v = max([dims[iDim],dims_rq[iDim]])
newdims.append(v)
# Resize if necessary
if newdims != dims:
self.resize(newdims,refcheck=False)
return super(marray, self).__setitem__(key, value)
它就像一个魅力!但是,我需要修改上面的代码,以便 setitem 允许在此请求之后更改维度数:
a = marray([0,0])
a[3,1,0] = 0
不幸的是,当我尝试使用诸如
之类的 numpy 函数时self = np.expand_dims(self,2)
返回的类型是 numpy.ndarray 而不是 main.marray。如果将 marray 作为输入提供,关于如何强制执行 numpy 函数输出 marray 的任何想法?我认为使用 array_wrap 应该是可行的,但我永远找不到确切的方法。任何帮助将不胜感激。
【问题讨论】:
-
您的
append-in-loop 算法需要二次方时间,因此对于大型数组来说会变得非常慢。 -
借此机会摆脱所有临时数组重新分配;)
-
a) 如果您不打算使用稀疏值,即您想按顺序设置它们,您可以使用类似 np.fromiter 的方法。 b) 如果您仍然打算使用 ndarray 子类,这篇文章应该澄清为什么不保留类型以及如何修复它docs.scipy.org/doc/numpy-1.10.1/user/basics.subclassing.html
标签: python arrays matlab numpy indexing