我知道如何切片一维序列: arr[start:end]
,并访问数组中的元素: el = arr[row][col]
。
现在,我正在尝试类似于slice = arr[0:2][0:2]
(其中arr
是一个numpy数组),但它没有给我前两行和前两列,而是重复了前两行。我刚刚做了什么,如何沿另一个维度切片?
如果您使用numpy
,那么这很容易:
slice = arr[:2,:2]
或者如果你需要0值,
slice = arr[0:2,0:2]
你会得到相同的结果。
*请注意,slice
实际上是一个内置类型的名称。通常,我建议给你的对象取一个不同的“名称”。
另一种方法,如果你正在使用列表的列表*:
slice = [arr[i][0:2] for i in range(0,2)]
(注意这里的0是不必要的:[arr[i][:2] for i in range(2)]
也可以工作。)
我在这里做的是逐行获取每个所需的行(arr[i]
)。然后,我从该行中切取我想要的列,并将其添加到我正在构建的列表中。
如果你尝试这样:arr[0:2]
,你会得到前两行,如果你再次切片arr[0:2][0:2]
,你只是再次切割了前两行。
*这对于NumPy数组实际上也有效,但与我上面发布的“本地”解决方案相比,速度会较慢。
arr[0:2][0:2]
与arr[row][col]
相比实际上是做什么的? - SlightlyCubana = [[1,2,3],[4,5,6],[7,8,9]]
,然后 a[0][:]=[1, 2, 3]
,但很奇怪的是 a[:][0]
仍然是 [1,2,3]
。我认为应该是 [1,4,7]
。如果您能告诉我这里错在哪里,我将不胜感激。 - Alexander Cskaa
的第一个元素并返回其副本”和“复制a
并返回副本的第一个元素”。解决方法是[x[0] for x in a]
,或者如果你在使用numpy
,就是a[:, 0]
。 - mgilsonnumpy
,它们实际上非常相似... 如果没有numpy,就会非常不同(在多维数组中更像C语言中的“指向数组的指针数组”)。 - mgilsona[:]
是一个副本,并用于避免多个指针引用相同的内存位置。我只是混淆了C和Python语法。 - Alexander Cska对于多维数组的切片,必须指定维度(即轴)。正如 OP 所指出的那样,arr[i:j][i:j]
和 arr[i:j]
是完全相同的,因为 arr[i:j]
沿着第一维(行)进行了切片,并且与 arr
具有相同数量的维度(您可以通过 arr[i:j].ndim == arr.ndim
进行确认);因此,第二个切片仍然沿着第一维进行切片(这已经被第一个切片完成了)。要沿着第二个维度进行切片,必须显式指定,例如:
arr[:2][:, :2] # its output is the same as `arr[:2, :2]`
:
表示在该轴上切片所有元素,因此在上述代码中第二个轴上有一个隐式的 :
(即 arr[:2, :][:, :2]
)。上述代码所做的是从结果数组中切取前两行(或第一轴上的前两个数组),然后再从中切取前两列(或第二轴上的前两个数组)。
可以使用 ...
代替多个冒号(:
),因此对于一般的 n 维数组,以下代码产生相同的输出:
w = arr[i:j, m:n]
x = arr[i:j, m:n, ...]
y = arr[i:j][:, m:n]
z = arr[i:j, ...][:, m:n, ...]
话虽如此,arr[:2, :2]
是规范的方式,因为在arr[i:j][:, i:j]
的情况下,arr[i:j]
创建了一个临时数组,该数组由[:, i:j]
索引,因此效率相对较低。
然而,在某些情况下,链式索引是有意义(或可读性更好),例如,如果您想使用索引列表来索引多维数组。例如,如果您想使用索引列表来切片4x4数组的左上角,则链式索引会给出正确的结果,而单个索引会给出不同的结果(这是由于numpy高级索引),其中值对应于索引列表中每个位置的索引对。
arr = np.arange(1,17).reshape(4,4)
rows = cols = [0,1]
arr[rows][:, cols] # <--- correct output
arr[rows, cols] # <--- wrong output
arr[[[e] for e in rows], cols] # <--- correct output
arr[np.ix_(rows, cols)] # <--- correct output
arr
是什么数据类型?它是一个列表的列表吗? - mgilson