Python 在不实际索引数组的情况下,如何获得已知形状数组的索引元素数?
我有一个索引Python 在不实际索引数组的情况下,如何获得已知形状数组的索引元素数?,python,arrays,numpy,numpy-ndarray,numpy-indexing,Python,Arrays,Numpy,Numpy Ndarray,Numpy Indexing,我有一个索引IDX(可能是索引列表、布尔掩码、切片元组等)索引已知形状形状的抽象numpy数组(可能很大) 我知道我可以创建一个虚拟数组,对它进行索引并计算元素: A = np.zeros(shape) print(A[IDX].size) 在不创建任何(可能较大的)数组的情况下,是否有任何合理的方法可以获得索引元素的数量 我需要将3D空间中某些点的函数列表制成表格。这些点是矩形网格的子集,表示为X,Y,Z列表,并且IDX正在索引其笛卡尔积: XX, YY, ZZ = [A[IDX] for
IDX
(可能是索引列表、布尔掩码、切片元组等)索引已知形状形状的抽象numpy数组(可能很大)
我知道我可以创建一个虚拟数组,对它进行索引并计算元素:
A = np.zeros(shape)
print(A[IDX].size)
在不创建任何(可能较大的)数组的情况下,是否有任何合理的方法可以获得索引元素的数量
我需要将3D空间中某些点的函数列表制成表格。这些点是矩形网格的子集,表示为X
,Y
,Z
列表,并且IDX
正在索引其笛卡尔积:
XX, YY, ZZ = [A[IDX] for A in np.meshgrid(X, Y, Z)]
这些函数接受X
,Y
,Z
参数(以及需要索引的笛卡尔积的返回值)或XX
,YY
,ZZ
。
此时,我创建了XX
、YY
和ZZ
数组,无论它们是否被使用,然后我为函数值分配了一个数组:
self.TAB = np.full((len(functions), XX.size),
np.nan)
但是我想创建XX
,YY
和ZZ
,只要它们是必要的。我还想将选项卡
分配与其行填充分开,因此我需要提前知道列的数量。只是为了好玩,让我们看看是否可以在这里做一个可接受的近似值。您的输入可以是以下任一项:
- 切片
- 类数组(包括标量)
- 整数数组不需要复杂的索引
- 布尔数组不做掩蔽
- 元组
如果输入不是一个明确的元组开始,使它成为一个元组。现在可以沿着元组进行迭代,并将其与形状匹配。您不能将它们完全压缩在一起,因为布尔数组占用了形状的多个元素,并且包含了大量的尾随轴
像这样的东西应该可以做到:
def pint(x):
""" Mimic numpy errors """
if isinstance(x, bool):
raise TypeError('an integer is required')
try:
y = int(x)
except TypeError:
raise TypeError('an integer is required')
else:
if y < 0:
raise ValueError('negative dimensions are not allowed')
return y
def estimate_size(shape, index):
# Ensure input is a tuple
if not isinstance(index, tuple):
index = (index,)
# Clean out Nones: they don't change size
index = tuple(i for i in index if i is not None)
# Check shape shape and type
try:
shape = tuple(shape)
except TypeError:
shape = (shape,)
shape = tuple(pint(s) for s in shape)
size = 1
# Check for scalars
if not shape:
if index:
raise IndexError('too many indices for array')
return size
# Process index dimensions
# you could probably use iter(shape) instead of shape[s]
s = 0
# fancy indices need to be gathered together and processed as one
fancy = []
def get(n):
nonlocal s
s += n
if s > len(shape):
raise IndexError('too many indices for array')
return shape[s - n:s]
for ind in index:
if isinstance(ind, slice):
ax, = get(1)
size *= len(range(*ind.indices(ax)))
else:
ind = np.array(ind, ndmin=1, subok=True, copy=False)
if ind.dtype == np.bool_:
# Boolean masking
ax = get(ind.ndim)
if ind.shape != ax:
k = np.not_equal(ind.shape, ax).argmax()
IndexError(f'IndexError: boolean index did not match indexed array along dimension {s - n.ndim + k}; dimension is {shape[s - n.ndim + k]} but corresponding boolean dimension is {ind.shape[k]}')
size *= np.count_nonzero(ind)
elif np.issubdtype(ind.dtype, np.integer):
# Fancy indexing
ax, = get(1)
if ind.min() < -ax or ind.max() >= ax:
k = ind.min() if ind.min() < -ax else ind.max()
raise IndexError(f'index {k} is out of bounds for axis {s} with size {ax}')
fancy.append(ind)
else:
raise IndexError('arrays used as indices must be of integer (or boolean) type')
# Add in trailing dimensions
size *= np.prod(shape[s:])
# Add fancy indices
if fancy:
size *= np.broadcast(*fancy).size
return size
def品脱(x):
“”“模拟numpy错误”“”
如果存在(x,布尔):
raise TypeError('需要整数')
尝试:
y=int(x)
除类型错误外:
raise TypeError('需要整数')
其他:
如果y<0:
raise VALUERROR('不允许负维度')
返回y
def估计尺寸(形状、索引):
#确保输入是一个元组
如果不是isinstance(索引、元组):
索引=(索引,)
#清理掉不需要的东西:它们不会改变大小
index=tuple(如果i不是None,则i代表索引中的i)
#检查形状和类型
尝试:
shape=元组(shape)
除类型错误外:
形状=(形状,)
形状=元组(形状为s的品脱)
尺寸=1
#检查标量
如果不是形状:
如果索引:
raise IndexError('数组的索引太多')
返回大小
#过程索引维度
#你可以用iter(形状)代替形状
s=0
#花式指数需要收集在一起,并作为一个整体进行处理
花式=[]
def get(n):
非局部s
s+=n
如果s>len(形状):
raise IndexError('数组的索引太多')
返回形状[s-n:s]
对于索引中的索引:
如果存在(ind,切片):
ax,=get(1)
尺寸*=长度(范围(*索引(ax)))
其他:
ind=np.array(ind,ndmin=1,subok=True,copy=False)
如果ind.dtype==np.bool\ux:
#布尔掩蔽
ax=获取(ind.ndim)
如果是ind.shape!=ax:
k=np.不相等(ind.shape,ax).argmax()
索引器(f'索引器:布尔索引与沿维度{s-n.ndim+k}的索引数组不匹配;维度为{shape[s-n.ndim+k]},但对应的布尔维度为{ind.shape[k]})
大小*=np.计数非零(ind)
elif np.issubdtype(ind.dtype,np.integer):
#花式索引
ax,=get(1)
如果ind.min()<-ax或ind.max()>=ax:
k=ind.min(),如果ind.min()<-ax else ind.max()
raise IndexError(f'index{k}超出大小为{ax}的轴{s}的界限)
花式追加(ind)
其他:
raise IndexError('用作索引的数组必须是整数(或布尔)类型')
#添加尾部尺寸标注
尺寸*=np.prod(形状:)
#添加花式索引
如果喜欢:
尺寸*=np.广播(*花式)。尺寸
返回大小
这只是一个近似值。您需要在API更改时随时更改它,并且它已经有一些不完整的特性。测试、修复和扩展留给读者作为练习。我想不出任何接近索引通用性的东西。有太多的选择。你为什么需要这个?也许你展示它的方式是最好的;否则,您必须找到每种类型的index@hpaulj请查看编辑如果您只需要XX.size
,您可能可以执行XX=np.meshgrid(X,Y,Z)[0][IDX]
,而不是现在执行的XX,YY,ZZ=[A[IDX]表示np.meshgrid(X,Y,Z)]
。据我所知,XX.size
、YY.size
和ZZ.size
的值都是相同的。@hpaulj。如果我错过了什么重要的事情,请告诉我。我确信我的答案没有涵盖所有的细节,但希望它涵盖了大部分的基础知识。如果ind.dtype
是整数,为什么我们要做size*=np.unique(ind%ax).size
?我本以为只要size*=ind.size
,但我相信你这么做是有原因的。唷,太复杂了+1已经存在。如果索引对象由两个整数数组组成,size
的值是提升了两次(使用size*=
)还是只提升了一次?(我希望这只是一次,但我只是想知道在哪里可以保证这一点)。@fountainhead。抢手货应该是一次,actu