使用numpy中的2-D索引的子样本1-D阵列

时间:2013-04-26 15:37:44

标签: python numpy indexing slice

背景 我正在使用的数据是从netCDF4对象中提取的,它在初始化时会创建一个numpy蒙版数组,但似乎不支持numpy reshape()方法,因此它只能重新整形数据已被复制=方式太慢。

问题:如何对1-D阵列进行子采​​样,基本上是扁平的2-D阵列,而不重新整形?

import numpy

a1 = np.array([[1,2,3,4],
               [11,22,33,44],
               [111,222,333,444],
               [1111,2222,3333,4444],
               [11111,22222,33333,44444]])

a2 = np.ravel(a1)

rows, cols = a1.shape

row1 = 1
row2 = 3

col1 = 1
col2 = 3

我想使用快速切片方法,不需要将1-D阵列重新整形为2-D阵列。

期望输出:

np.ravel(a1[row1:row2, col1:col2])

>> array([ 22,  33, 222, 333])

我得到了开始和结束位置,但这只是选择这些点之间的所有数据(即额外的列)。

idx_start = (row1 * cols) + col1
idx_end   = (row2 * cols) + col2

更新 我刚试过Jaime's brilliant answer,但似乎netCDF4不允许使用二维索引。

z = dataset.variables["z"][idx]
  File "netCDF4.pyx", line 2613, in netCDF4.Variable.__getitem__ (netCDF4.c:29583)
  File "/usr/local/lib/python2.7/dist-packages/netCDF4_utils.py", line 141, in _StartCountStride
    raise IndexError("Index cannot be multidimensional.")
IndexError: Index cannot be multidimensional.

3 个答案:

答案 0 :(得分:1)

您可以通过np.ogridnp.ravel_multi_index组合获得所需内容:

>>> a1
array([    1,     2,     3,     4,    11,    22,    33,    44,   111,
         222,   333,   444,  1111,  2222,  3333,  4444, 11111, 22222,
       33333, 44444])
>>> idx = np.ravel_multi_index((np.ogrid[1:3,1:3]), (5, 4))
>>> a1[idx]
array([[ 22,  33],
       [222, 333]])

如果你正在追求的话,你当然可以将这个阵列拉平以获得1D回报。另请注意,这是原始数据的副本,而不是视图。


编辑您可以采用相同的一般方法,将np.ogrid替换为np.mgrid并重新整形以获得平坦的回报:

>>> idx = np.ravel_multi_index((np.mgrid[1:3,1:3].reshape(2, -1)), (5, 4))
>>> a1[idx]
array([ 22,  33, 222, 333])

答案 1 :(得分:0)

我想出了这个,虽然它没有复制所有数据,但它仍然将我不想要的数据复制到内存中。这可能会有所改善,我希望有更好的解决方案。

zi = 0 
# Create zero array with the appropriate length for the data subset
z = np.zeros((col2 - col1) * (row2 - row1))
# Process number of rows for which data is being extracted
for i in range(row2 - row1):
    # Pull row, then desired elements of that row into buffer
    tmp = ((dataset.variables["z"][(i*cols):((i*cols)+cols)])[col1:col2])
    # Add each item in buffer sequentially to data array
    for j in tmp:
        z[zi] = j 
        # Keep a count of what index position the next data point goes to
        zi += 1

答案 2 :(得分:0)

这是一个精益主张

a1 = np.array([[1,2,3,4],
               [11,22,33,44],
               [111,222,333,444],
               [1111,2222,3333,4444],
               [11111,22222,33333,44444]])

row1 = 1; row2 = 3; ix = slice(row1,row2)
col1 = 1; col2 = 3; iy = slice(col1,col2)
n = (row2-row1)*(col2-col1)

print(a1[ix,iy]);    print()
print(a1[ix,iy].reshape(1,n))
.
[[ 22  33]
 [222 333]]

[[ 22  33 222 333]]

重塑Python并不贵,slice is fast