解析Numpy切片操作后的数组形状异常问题
解析Numpy链式切片的形状异常问题
我来帮你拆解这个Numpy切片的误区,问题核心在于你用的链式切片写法和Numpy多维数组的切片逻辑完全不一样~
先回顾你的数据情况:
>>> original_data.shape (220, 145, 145) >>> all_data = np.transpose(original_data, (1,2,0)) >>> all_data.shape (145, 145, 220)
为什么original_data[:][:][0]得到(145,145)?
你以为[:][:][0]是在第三个维度取第0个元素,但Numpy里的链式切片是依次对每一步的结果做一维操作:
original_data[:]:返回整个数组,形状还是(220,145,145)- 再做
[:]:依然返回整个数组,形状不变 - 最后
[0]:对当前数组(形状(220,145,145))取第一个维度的第0个元素,也就是形状为(145,145)的子数组
这和你预期的(220,145)完全不符,因为你真正想取的是第三个维度的第0个元素,正确写法应该是original_data[:,:,0],这个写法会同时指定三个维度的切片规则:第一个维度全取,第二个维度全取,第三个维度取第0个,结果形状就是(220,145)。
为什么all_data的链式切片结果不符合预期?
同样的逻辑,all_data[:][:][0]的执行过程是:
all_data[:]返回整个数组,形状(145,145,220)- 再
[:]还是整个数组 [0]取第一个维度的第0个元素,也就是形状(145,220)的子数组
而你想要的是第三个维度的第0个元素,正确写法是all_data[:,:,0],执行后形状就是(145,145),完全符合预期。
其他链式切片的结果解释
比如你尝试的:
>>> temp = all_data[:][0][:] >>> temp.shape (145, 220)
这等价于((all_data[:])[0])[:]:
all_data[:]是整个数组[0]取第一个维度的第0个元素,形状(145,220)[:]返回这个子数组的全部元素,形状不变
再比如:
>>> temp = all_data[0][:][:] >>> temp.shape (145, 220)
等价于((all_data[0])[:])[:],第一步all_data[0]就取了第一个维度的第0个元素,后面的[:][:]不改变形状,结果自然是(145,220)。
关键总结
Numpy多维数组的切片,要同时对多个维度指定规则,必须用逗号分隔的索引语法(比如arr[dim1_slice, dim2_slice, dim3_slice]);而链式的[:][:][...]是依次对每一步的数组做一维索引/切片,每一步的操作只作用于当前数组的第一个维度,这就是你得到不符合预期形状的根本原因。
内容的提问来源于stack exchange,提问作者Emile Engelbrecht
相关产品推荐
相关产品推荐

