结合选择器条件

时间:2014-08-15 13:44:32

标签: python numpy

我希望结合几个条件来从数组中选择行/列。

给定矩阵A,我知道

A[:, [1,3]] 

给了我第二和第四列。另外,

A[:, :3]

就像一个魅力。但是,我没有结合条件:

A[:, [:3, 6, 7]]

给我一​​个语法错误。我怎样才能选择这个选择?

2 个答案:

答案 0 :(得分:5)

简而言之,您可以这样做:

A[:, range(3) + [6, 7]]

A[:, np.r_[:3, 6, 7]]

要理解为什么你的第一次尝试没有用,你需要更多地了解一般的python索引以及numpy的索引是如何工作的。


首先,切片表示法仅在切片内有效,因此blah = [:3, 6, 7]是无效的python语法,因为在这种情况下您正在构建新的列表。 (你用A[:, [:3, 6, 7]]隐式地做这个。第二组括号创建一个新列表。)Numpy有一个特殊的(但经常讨厌)运算符使用切片表示法来构造类似于你的东西# 39;想要:np.r_。例如:

In [1]: print np.r_[:3, 6, 7]
[0 1 2 6 7]

请注意,我们可以通过添加两个列表来获得或多或少相同的结果(np.r_返回数组,下一个示例将返回list):

In [2]: print range(3) + [6, 7]
[0, 1, 2, 6, 7]

然而,理解窗帘背后发生的事情也很重要。 numpy中有两种常见的索引类型。 "正常"索引使用任何排序的切片并返回数组的视图。数据未被复制。 "花式"索引使用任意序列的项(例如列表)并复制数据。

因为标准切片表示法可以描述的任何内容都有常规步骤(即开始,结束和步骤间隔),所以您可以创建新数组而无需复制原始数据。 (Numpy数组必须"经常跨越#34;在内存中。你可以引用"每三个项目"不复制数据,但不能"项目2,5和6"因为后者没有规律的模式。)

所有这一切可能看起来令人困惑,但这里有一个重要原因的例子。让我们做一个示例数组并将它切成两种不同(但相当)的方式:

In [1]: a = np.arange(18).reshape(3, 6)

In [2]: a
Out[2]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17]])

In [3]: b = a[:, :3]

In [4]: b
Out[4]:
array([[ 0,  1,  2],
       [ 6,  7,  8],
       [12, 13, 14]])

In [5]: c = a[:, [0, 1, 2]]

In [6]: c
Out[6]:
array([[ 0,  1,  2],
       [ 6,  7,  8],
       [12, 13, 14]])

bc看起来相同。但是,ca中数据的新副本,b引用原始数据。如果我们更改c,则a无法修改:

In [7]: c[0, 0] = 10000

In [8]: c
Out[8]:
array([[10000,     1,     2],
       [    6,     7,     8],
       [   12,    13,    14]])

In [9]: a
Out[9]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17]])

如果我们更改ba 将被修改

In [10]: a
Out[10]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17]])

In [11]: b[0,0] = 99999

In [12]: a
Out[12]:
array([[99999,     1,     2,     3,     4,     5],
       [    6,     7,     8,     9,    10,    11],
       [   12,    13,    14,    15,    16,    17]])

In [13]: b
Out[13]:
array([[99999,     1,     2],
       [    6,     7,     8],
       [   12,    13,    14]])

这使您可以对内存使用进行大量控制,并且允许numpy非常高效(当您开始在内存中使用非常大的数组时,它的非常非常重要。)。但是,如果你不知道发生了什么,你可能会被它烧掉。

答案 1 :(得分:0)

不确定这是不是您要找的东西:

>>> A = numpy.array([range(10)]*10)
>>> numpy.hstack((A[:, :3],A[:, [6,7]]))
array([[0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7],
       [0, 1, 2, 6, 7]])
>>>