简体   繁体   English

构建一个包含冒号的元组,用于索引一个 numpy 数组

[英]Building a tuple containing colons to be used to index a numpy array

I've created a class for dealing with multidimensional data of a specific type.我创建了一个用于处理特定类型的多维数据的类。 This class has three attributes: A list containing the names of the axes ( self.axisNames );此类具有三个属性: 包含轴名称的列表 ( self.axisNames ); a dictionary containing the parameter values along each axis ( self.axes ; keyd using the entries in axisNames);包含沿每个轴的参数值的字典( self.axes ;使用轴名称中的条目键入); and a numpy array containing the data, with a dimension for each axis ( self.intensityArr ).和一个包含数据的 numpy 数组,每个轴都有一个维度( self.intensityArr )。

The class also has functions that dynamically add new axes depending on what I need for a specific case, which makes indexing the intensityArr a tricky proposition.该类还具有根据我对特定情况的需要动态添加新轴的函数,这使得索引强度 Arr 成为一个棘手的命题。 To make indexing better I've started writing a function to build the index I need:为了更好地建立索引,我开始编写一个函数来构建我需要的索引:

Inside class:内课:

def indexIntensityArr(self,indexSpec):
    # indexSpec is a dictionary containing axisName:indexVal entries (indexVal is an int)
    # I want the function to return a tuple for use in indexing (see below def)
    indexList = []
    for axis in self.axisNames:
        if axis in indexSpec:
            indexList.append(indexSpec[axis])
        else:
            # <do something to add : to index list (tuple)>
    return tuple(indexList)

Outside class:课外:

# ... create an instance of my class called myBlob with 4 dimensions ...

mySpec = {'axis1':10,'axis3':7}
mySlicedArr = myBlob.intensityArr[myBlob.indexIntensityArr(mySpec)]

I expect the above to result in mySlicedArr being a 2-dimensional array.我希望上面的结果 mySlicedArr 是一个二维数组。

What do I need to put in the 'else' clause to get an : (or equivalent) in the tuple I use to index the intensityArr?我需要在“else”子句中添加什么才能在用于索引强度Arr的元组中获得 :(或等效项)? Is this perhaps a bad way to solve the problem?这可能是解决问题的糟糕方法吗?

Inside indexing [] , a : is translated to a slice , and the whole thing is passed to __getitem__ as a tuple在索引[] ,一个:被转换为一个slice ,整个内容作为一个元组传递给__getitem__

indexList = []
for axis in self.axisNames:
    if axis in indexSpec:
        indexList.append(indexSpec[axis])
    else:
        indexList.append(slice(None))

There are several numpy functions that use an indexing trick like this - that is build up a tuple of index values and slices.有几个numpy函数使用这样的索引技巧 - 即构建索引值和切片的元组。 Or if they need to vary it, they'll start with a list, which can mutate, and convert it to a tuple right before use.或者,如果他们需要改变它,他们将从一个列表开始,该列表可以变异,并在使用前将其转换为元组。 (eg np.apply_along_axis ) (例如np.apply_along_axis

Yes, the full spec for slice is slice(start, stop, step) , with start and stop optional.是的,切片的完整规范是slice(start, stop, step) ,开始和停止是可选的。 Same as for np.arange or range .np.arangerange相同。 And None is equivalent to the unspecified values in a : expression.None等价于:表达式中未指定的值。

A little custom class in np.lib.index_tricks.py translates the : notation into slices: np.lib.index_tricks.py一个小自定义类将 : 符号转换为切片:

In [61]: np.s_[:,:1,0:,::3]
Out[61]: 
(slice(None, None, None),
 slice(None, 1, None),
 slice(0, None, None),
 slice(None, None, 3))

To add to hpaulj's answer, you can very simply extend your setup to make it even more generic by using np.s_ .要添加到 hpaulj 的答案中,您可以非常简单地扩展您的设置,通过使用np.s_使其更加通用。 The advantage of using this over slice is that you can use numpy 's slice syntax more easily and transparently.slice上使用它的优点是您可以更轻松、更透明地使用numpy的切片语法。 For example:例如:

mySpec = {'axis1': np.s_[10:15], 'axis3': np.s_[7:8]}
mySlicedArr = myBlob.intensityArr[myBlob.indexIntensityArr(mySpec)]

(Extra info: np.s_[7:8] retrieves only the 7th column, but it preserves the dimension, ie your sliced array will still be 4D with a shape of 1 in that dimension: very useful for broadcasting). (额外信息: np.s_[7:8]仅检索第 7 列,但它保留了维度,即您的切片数组仍将是 4D,该维度的形状为 1:对于广播非常有用)。

And if you want to use the same syntax in your function definition as well:如果您还想在函数定义中使用相同的语法:

indexList = []
for axis in self.axisNames:
    if axis in indexSpec:
        indexList.append(indexSpec[axis])
    else:
        indexList.append(np.s_[:])
return tuple(indexList)

All of this can be done equally well with slice .所有这些都可以通过slice来完成。 You would specify np.s_[10:15] as slice(10, 15) , and np.s_[:] as slice(None) , as hpaulj says. np.s_[10:15]您可以将np.s_[10:15]指定为slice(10, 15) ,将np.s_[:]slice(None)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM