在Python中,访问数组列的最佳方式是什么?

6
在Matlab中,可以使用:来访问数组的一列。
>> array=[1 2 3; 4 5 6]

array =

     1     2     3
     4     5     6


>> array(:,2)

ans =

     2
     5

如何在Python中实现此功能?

>>> array=[[1,2,3],[4,5,6]]
>>> array[:,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not tuple
>>> array[:][2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

附录

我希望有一个示例应用于三维以上的数组:

>> B = cat(3, eye(3), ones(3), magic(3))

B(:,:,1) =

     1     0     0
     0     1     0
     0     0     1


B(:,:,2) =

     1     1     1
     1     1     1
     1     1     1


B(:,:,3) =

     8     1     6
     3     5     7
     4     9     2

>> B(:,:,1)                             

ans =

     1     0     0
     0     1     0
     0     0     1

>> B(:,2,:)

ans(:,:,1) =

     0
     1
     0


ans(:,:,2) =

     1
     1
     1


ans(:,:,3) =

     1
     5
     9
7个回答

15

使用Numpy

>>> import numpy as np
>>> 
>>> a = np.array([[1,2,3],[4,5,6]])
>>> a[:, 2]
array([3, 6])

如果您来自Matlab,这应该会引起您的兴趣:链接


1
如@unutbu所说,为了在Python中实现与Matlab中的array(:,2)相同的效果,请使用a[:, 1],因为Python是从0开始计数的。 - Bruno
不确定问题是一般性的还是想要使用一些数值代码。如果是后者,你绝对应该研究一下Numpy/Scipy(也许还取决于你所做的事情而考虑SciKits)。我不会尝试在Python中编写数值代码,而没有专门用于此目的的库。 - Bruno
如何处理维度大于3的数组? - qazwsx

8

您可以使用内置的zip()函数按列将数据分组为二维列表:

>>> array=[[1,2,3],[4,5,6]]
>>> zip(*array)
[(1, 4), (2, 5), (3, 6)]
>>> zip(*array)[1]
(2, 5)

请注意索引从0开始,所以要像您的示例中获取第二列,您需要使用zip(*array)[1]而不是zip(*array)[2]zip()返回元组而不是列表,根据您使用它的方式,这可能不是问题,但如果您需要列表,您可以始终执行map(list,zip(*array))list(zip(*array)[1])进行转换。

所以这只是矩阵转置。有没有将其转换为元组的特殊注释? - qazwsx

4
如果您使用Matlab,您可能需要安装NumPy: 使用NumPy,您可以做到这一点:
In [172]: import numpy as np

In [173]: arr = np.matrix('1 2 3; 4 5 6')

In [174]: arr
Out[174]: 
matrix([[1, 2, 3],
        [4, 5, 6]])

In [175]: arr[:,2]
Out[175]: 
matrix([[3],
        [6]])

由于Python使用基于0的索引(而Matlab使用基于1的索引),要获得您发布的相同切片,您需要执行以下操作:

In [176]: arr[:,1]
Out[176]: 
matrix([[2],
        [5]])

构建更高维度的numpy数组也很容易。例如,您可以使用np.dstack

In [199]: B = np.dstack( (np.eye(3), np.ones((3,3)), np.arange(9).reshape(3,3)) )

In [200]: B.shape
Out[200]: (3, 3, 3)

In [201]: B[:,:,0]
Out[201]: 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

In [202]: B[:,:,1]
Out[202]: 
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

In [203]: B[:,:,2]
Out[203]: 
array([[ 0.,  1.,  2.],
       [ 3.,  4.,  5.],
       [ 6.,  7.,  8.]])

以下是从上述3个数组的第二列形成的数组:

In [204]: B[:,1,:]
Out[204]: 
array([[ 0.,  1.,  1.],
       [ 1.,  1.,  4.],
       [ 0.,  1.,  7.]])

Numpy没有创建幻方的函数。 嗅嗅

1
+1 对于数组索引的捕捉很好。不过我会使用数组而不是矩阵。来自这里:"'array'或'matrix'? 我应该使用哪个? 简短回答:使用数组。" - Bruno
是的,我同意您的偏好。一般来说,使用数组。不过将一个转换为另一个很容易:arr = np.asarray(arr) - unutbu

2

使用冒号在Python中进行索引/切片与matlab有些不同。如果你有一个数组,[:]将对其进行复制。如果你想要嵌套数组中特定索引处的所有值,你可能需要像这样:

array = [[1,2,3],[4,5,6]]
col1 = [inner[0] for inner in array] # note column1 is index 0 in Python.

2
如果使用嵌套列表,你可以使用列表推导式:
array = [ [1, 2, 3], [4, 5, 6] ]
col2 = [ row[1] for row in array ]

请注意,由于Python本身不支持矩阵操作,col2是一个列表,因此“行”和“列”都是同样的类型,即列表。使用numpy包可以更好地支持矩阵计算。


0
def get_column(array, col):
  result = []
  for row in array:
    result.appen(row[col])
  return result

使用方法如下(请记住索引从0开始):

>>> a = [[1,2,3], [2,3,4]]
>>> get_column(a, 1)
[2, 3]

你拼错了 .append。此外,列表推导式比逐个构建列表要好得多。 - Kirk Strauser

0
使用列表推导式从该列构建一个值列表:
def nthcolumn(n, matrix):
    return [row[n] for row in matrix]

如果你需要(可能是轻微的)性能提升,可以选择使用itemgetter

from operator import itemgetter

def nthcolumn(n, matrix):
    nthvalue = itemgetter(n)
    return [nthvalue(row) for row in matrix]

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