在Python的NumPy数组中,A[0]和A[0:1]有什么区别?

7

我有一个像这样的numpy数组:

candidates = 

array([[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,
        0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
        0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1],
       [1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
        0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0]])

我不明白candidates[0]有什么区别:

candidates[0] = 

array([1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,
       0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0]

candidates[0].shape = (34,)

还有candidates[0:1]

candidates[0:1] = 

array([[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0,
        0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0]])

candidates[0:1].shape = (1, 34)

我认为两者应该给出完全相同的结果,因为后面的 candidates[0:1] 应该只表示第一个元素,对吧?那么,这两者之间到底有什么区别呢?


4
这段话的意思是:这里的切片方式与普通的Python切片方式相同:candidates[0]表示第一个元素(在本例中,即第一行);candidates[0:1]表示前一个元素的集合(在本例中,即只包含第一行的二维数组)。这就是形状不同的原因。比较一下lst = [1,2,3]lst[0]lst[0:1]:其中一个是1,另外一个是[1] - abarnert
@decadenza(另外,您链接的问题本身也被关闭为dup of this one,我认为它有一个更好的答案 - 但幸运的是,如果我们想要关闭它,我们可以链接两个问题。) - abarnert
@abarnert 谢谢您的回复!我显然知道 [0][0:1] 之间的区别。我只是需要理解后者会产生一个二维数组。不知道是否应该从问题中删除“大小”这个词以避免混淆?或者如果您认为您可以改进我的措辞,请继续,因为英语不是我的母语哈哈。谢谢! - RezAm
@Antonio,其他答案是否解决了你的问题?是因为形状为(1, 34)让你感到困惑,还是因为[0:1]返回一个二维数组让你感到困惑? - abarnert
@abarnert,不,这些问题的答案与我的困惑无关。我只是不明白[0]是索引,而[0:1]是切片,并导致2D数组。顺便说一下,我从我的问题中删除了“size”这个词。如果您愿意,请随意改进它。谢谢! - RezAm
显示剩余3条评论
3个回答

10

在Python中,[0]表示是索引操作,它返回第一个元素,而[0:1]表示是切片操作,它返回前1个元素的集合。

这可能更容易理解,使用一个普通的列表:

>>> lst = [1, 2, 3]
>>> lst[0]
1
>>> lst[0:1]
[1]
Numpy扩展了Python的索引和切片功能,其中一些会给您提供一个2D结果,出于不同的原因。例如,您可以像使用索引数组一样使用[0]作为类似“数组”的索引,但相关基础知识在这里是相同的。对于一个2D的numpy数组,元素是行,所以candidates[0]是第一行——一个1D数组,而candidates[0:1]是所有第一行的数组——一个2D数组。因此,第一个形状为(34,),第二个形状为(1, 34)
如果您没有仔细查看,可能不会注意到这两者之间的区别,但请比较它们的起始方式:
array([1,
array([[1,

它们没有排成一行,因为第二个括号有两个而不是一个,这是因为它是一个二维数组而不是一维数组。


1
@jpp 实际上,这不是切片,而是使用类似数组的索引。我认为深入研究numpy扩展索引(和切片)的所有不同方法可能会使事情变得过于复杂化。 - abarnert
1
@jpp 或许值得在“Numpy扩展了索引和切片”的短语中加入一个例子,这样会更好些。 - abarnert
是的 - 这可能有所帮助。不确定最好的措辞方式。 - jpp

2

区别在于维度的数量:candidates[0:1]将返回一个二维数组,而candidates[0]将返回一个一维数组:

>>> candidates[0:1].ndim
2
>>> candidates[0].ndim
1

通过candidates[0:1]的输出,您也可以“看到”数组的维度:注意数组周围方括号的数量。这些方括号可以提示数组的维度。


2
不。区别在于你的数组形状不同。在第一种情况下,你有一个一维数组。在第二种情况下,你有一个二维数组。
你可以通过测试数组的“shape”属性来进行测试:
print(np.array([[1, 0]]).shape)
(1, 2)

print(np.array([1, 0]).shape)
(2,)

通过使用一个元素列表,比如[0:1]来切片数组,你的结果将会增加一个维度。请注意这与使用范围无关;当你使用一个只有1个元素的列表作为索引器时,这也是正确的:

x = np.array([[0, 1], [2, 3]])

print(x[[0]].shape)
# (1, 2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接