簡體   English   中英

將切片和廣播索引相結合以實現多維numpy數組

[英]Combining slicing and broadcasted indexing for multi-dimensional numpy arrays

我有一個ND numpy數組(例如3x3x3),我想提取一個子數組,結合切片和索引數組。 例如:

import numpy as np  
A = np.arange(3*3*3).reshape((3,3,3))
i0, i1, i2 = ([0,1], [0,1,2], [0,2])
ind1 = j0, j1, j2 = np.ix_(i0, i1, i2)
ind2 = (j0, slice(None), j2)
B1 = A[ind1]
B2 = A[ind2]

我希望B1 == B2,但是實際上,形狀是不同的

>>> B1.shape
(2, 3, 2)
>>> B2.shape
(2, 1, 2, 3)
>>> B1
array([[[ 0,  2],
        [ 3,  5],
        [ 6,  8]],

       [[ 9, 11],
        [12, 14],
        [15, 17]]])
>>> B2
array([[[[ 0,  3,  6],
         [ 2,  5,  8]]],

       [[[ 9, 12, 15],
         [11, 14, 17]]]])

有人知道為什么嗎? 關於如何僅通過操作“ A”和“ ind2”對象來獲得“ B1”的任何想法嗎? 目標是它適用於任何nD數組,並且我不必尋找要完全保留的尺寸形狀(希望我已經很清楚了:)。 謝謝!!
- -編輯 - -
更清楚地說,我想有一個功能“有趣”,使

A[fun(ind2)] == B1

ind1的索引子空間為(2,),(3,),(2,),結果B(2,3,2) 這是高級索引的簡單情況。

ind2是(高級)部分索引的一種情況。 有2個索引數組和1個切片。 高級索引文檔指出:

如果索引子空間是分離的(按切片對象划分),則首先廣播的索引空間,然后是x的切片子空間。

在這種情況下,高級索引從第一個索引和第三個索引構造一個(2,2)數組,並在末尾附加切片尺寸,從而得到一個(2,2,3)數組。

我會在https://stackoverflow.com/a/27097133/901925中更詳細地說明推理的原因

修復像ind2這樣的元組的一種方法是將每個slice擴展成一個數組。 我最近在np.insert看到了這一點。

np.arange(*ind2[1].indices(3))

擴展:[0,1,2] 但是替換必須具有正確的形狀。

ind=list(ind2)
ind[1]=np.arange(*ind2[1].indices(3)).reshape(1,-1,1)
A[ind]

我將省略確定哪個術語是一個切片,其尺寸以及相關重塑的詳細信息。 目的是復制i1

如果索引不是由ix_生成的,則重塑ix_難度可能更大。 例如

A[np.array([0,1])[None,:,None],:,np.array([0,2])[None,None,:]] # (1,2,2,3)
A[np.array([0,1])[None,:,None],np.array([0,1,2])[:,None,None],np.array([0,2])[None,None,:]]
# (3,2,2)

擴展的片必須與廣播中的其他陣列兼容。

索引后交換軸是另一種選擇。 但是,邏輯可能更復雜。 但是在某些情況下,移置實際上可能更簡單:

A[np.array([0,1])[:,None],:,np.array([0,2])[None,:]].transpose(2,0,1)
# (3,2,2)
A[np.array([0,1])[:,None],:,np.array([0,2])[None,:]].transpose(0,2,1)
# (2, 3, 2)

這是我能更接近您的規格的信息,我無法設計出一種在不知道A (或更確切地說,其形狀...)的情況下可以計算正確索引的解決方案。

import numpy as np  

def index(A, s):
    ind = []
    groups = s.split(';')
    for i, group in enumerate(groups):
        if group == ":":
            ind.append(range(A.shape[i]))
        else:
            ind.append([int(n) for n in group.split(',')])
    return np.ix_(*ind)

A = np.arange(3*3*3).reshape((3,3,3))

ind2 = index(A,"0,1;:;0,2")
print A[ind2]

較短的版本

def index2(A,s):return np.ix_(*[range(A.shape[i])if g==":"else[int(n)for n in g.split(',')]for i,g in enumerate(s.split(';'))])

ind3 = index2(A,"0,1;:;0,2")
print A[ind3]

在使用ix_這樣的受限索引情況下,可以ix_索引。

A[ind1]

是相同的

A[i1][:,i2][:,:,i3]

由於i2是完整范圍,

A[i1][...,i3]

如果您只有ind2

A[ind2[0].flatten()][[ind2[2].flatten()]

在更一般的上下文中,您必須知道j0,j1,j2如何相互廣播,但是當它們由ix_生成時,關系很簡單。

我可以想象一下這樣的情況:分配A1 = A[i1]並隨后進行涉及A1的各種動作(包括但不限於A1[...,i3] 您必須知道什么時候A1是視圖,什么時候是副本。

另一個索引工具是take

A.take(i0,axis=0).take(i2,axis=2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM