我是python的新手,所以我习惯使用array[i][j]
代替array[i,j]
。今天我按照教程创建的脚本在我发现我正在使用
numpy.dot(P[0][:], Q[:][0])
而不是
numpy.dot(P[0,:], Q[:,0])
由于某种原因,第二个工作,而第一个给我一个形状错误。矩阵维度为MxK和KxN。
我尝试同时打印P[0][:]
和P[0,:]
,运行id()
,type()
和P[0][:].shape
,但无法找到理由。为什么这些事情会有所不同?
我在Jupyter Notebook 4.3.0和Python 2.7.13上运行它。
答案 0 :(得分:4)
在处理numpy数组时,您应该几乎总是使用[i, j]
而不是[i][j]
。在许多情况下,没有真正的区别,但在你的情况下有。
假设你有一个这样的数组:
>>> import numpy as np
>>> arr = np.arange(16).reshape(4, 4)
>>> arr
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
当您使用与新视图等效的[:]
时,如果您执行[1, :]
或[:, 1]
,则表示获取第二行(列)。粗略地说,它意味着:索引您拥有数字的维度,并将维度保留在仅:
的位置:
>>> arr[:]
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> arr[:, 1] # get the second column
array([ 1, 5, 9, 13])
>>> arr[:][1] # get a new view of the array, then get the second row
array([4, 5, 6, 7])
这是因为[1]
被解释为[1, ...]
(...
是省略号对象),而对于2D,它等同于[1, :]
。
这也是行索引仍然有效的原因(因为它是第一个维度):
>>> arr[1, :] # get the second row
array([4, 5, 6, 7])
>>> arr[1][:] # get the second row, then get a new view of that row
array([4, 5, 6, 7])
答案 1 :(得分:3)
x[:]
生成列表的浅表副本,但在x
是数组时几乎无用。它创建一个新的view
- 相同的数据和形状,但不同的数组对象。如果这令人困惑,您需要查看一些有关视图和副本的基本numpy
文档。
在A[0,:]
或A[:, 1:5]
等二维数组中,:
是一种占位符,用于标识将作为整体使用的维度。 :
由Python解释器转换为slice(None,None,None)
,而start:stop:step
生成slice(start, stop, step)
。
A[0,:]
,可以缩短为A[0]
,意味着选择A的第一行'及其所有'列'。该操作推广到更高维度,其中行和列等名称具有不太直观的含义。
A[:,0]
表示选择第0列和所有行。
A[0][:]
扩展为A[0,:][:]
,表示将[:]
应用于A[0,:]
的结果,实际上,只需查看第1行(即1d)数组)。
A[:][0]
与A[:,0]
不同;它与A[0,:]
相同。 A[:]
与A[:,:]
整个2d数组的视图相同。
如果有帮助,我可以将索引表达式扩展为对A.__getitem__(...)
的调用。每组[]
都是一个单独的扩展。
在表达式A[:] = ...
中,[:]
很重要,但这是另一个主题。
这两个表达式是等价的:
numpy.dot(P[0][:], Q[:][0])
numpy.dot(P[0,:], Q[0,:])