Python numpy中的数组操作

Python numpy中的数组操作,python,arrays,numpy,Python,Arrays,Numpy,在长期使用R之后,我重新使用Python,发现数组的计算不是很方便。数组不能按行名和列名编制索引。我希望有人能帮助我,并向我展示如何以Pythonic的方式操纵数组 我有两个numpy数组 a = np.arange(12).reshape(3,4) >>> a array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) b = np.arange(20).reshape(4,5).T

在长期使用R之后,我重新使用Python,发现数组的计算不是很方便。数组不能按行名和列名编制索引。我希望有人能帮助我,并向我展示如何以Pythonic的方式操纵数组

我有两个
numpy
数组

a = np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

b = np.arange(20).reshape(4,5).T + 10
>>> b
array([[10, 15, 20, 25],
       [11, 16, 21, 26],
       [12, 17, 22, 27],
       [13, 18, 23, 28],
       [14, 19, 24, 29]])
和每个数组的行名称

a_rownames = ["m1", "m2", "m3"]
b_rownames = ["m1", "m2", "m1", "m3", "m2"]
任务是用
a
中的相应值替换数组
b
中指定列
columns\u id
的值。两个数组
a
b
中的列顺序相同

columns_ids = [False, True, False, True]
预期产出:

array([[10,  1, 20,  3],
       [11,  5, 21,  7],
       [12,  1, 22,  3],
       [13,  9, 23, 11],
       [14,  5, 24,  7]])

如何有效地做到这一点?

如果您暂时放弃姓名,这并不难:

import numpy

a = numpy.arange(12).reshape(3,4)
b = numpy.arange(20).reshape(4,5).T + 10

b_rows = [0, 1, 0, 2, 1]
columns_ids = numpy.array([False, True, False, True])

b[:, columns_ids] = a[:, columns_ids][b_rows]

b
#>>> array([[10,  1, 20,  3],
#>>>        [11,  5, 21,  7],
#>>>        [12,  1, 22,  3],
#>>>        [13,  9, 23, 11],
#>>>        [14,  5, 24,  7]])
如果确实需要外部名称数组:

a = numpy.arange(12).reshape(3,4)
b = numpy.arange(20).reshape(4,5).T + 10

a_rownames = numpy.array(["m1", "m2", "m3"])
b_rownames = numpy.array(["m1", "m2", "m1", "m3", "m2"])

_, b_rows = numpy.where(a_rownames == b_rownames[:, numpy.newaxis])

b[:, columns_ids] = a[:, columns_ids][b_rows]

b
#>>> array([[10,  1, 20,  3],
#>>>        [11,  5, 21,  7],
#>>>        [12,  1, 22,  3],
#>>>        [13,  9, 23, 11],
#>>>        [14,  5, 24,  7]])

这一魔法有三个步骤:

_, b_rows = numpy.where(a_rownames == b_rownames[:, numpy.newaxis])
首先,我们生成两个垂直阵列:

a_rownames
#>>> array(['m1', 'm2', 'm3'],
#>>>       dtype='<U2')

b_rownames[:, numpy.newaxis]
#>>> array([['m1'],
#>>>        ['m2'],
#>>>        ['m1'],
#>>>        ['m3'],
#>>>        ['m2']],
#>>>       dtype='<U2')
numpy。其中
给出了
xs
ys
对该数组进行索引,以获得所有
真值。我们只对
ys
感兴趣,因此忽略
xs

_, b_rows = numpy.where(a_rownames == b_rownames[:, numpy.newaxis])

另一个魔法:

b[:, columns_ids] = a[:, columns_ids][b_rows]
需要了解两种不同类型的索引:

  • 使用布尔数组进行索引会过滤数组

  • 使用整数数组进行索引将获取这些索引处的行

索引式

array[xs]

(由于广播原因,它们是相同的)将为您提供根据上述规则匹配的所有索引,并在第一个轴中过滤

使用

将在第二个轴中过滤

所以首先我们过滤列(第二个轴)

然后我们过滤
a
(第一个轴)上的行:

它们现在是相同的形状,因此可以执行切片指定:

b[:, columns_ids] = a[:, columns_ids][b_rows]

如果你暂时放弃名字,这并不难:

import numpy

a = numpy.arange(12).reshape(3,4)
b = numpy.arange(20).reshape(4,5).T + 10

b_rows = [0, 1, 0, 2, 1]
columns_ids = numpy.array([False, True, False, True])

b[:, columns_ids] = a[:, columns_ids][b_rows]

b
#>>> array([[10,  1, 20,  3],
#>>>        [11,  5, 21,  7],
#>>>        [12,  1, 22,  3],
#>>>        [13,  9, 23, 11],
#>>>        [14,  5, 24,  7]])
如果确实需要外部名称数组:

a = numpy.arange(12).reshape(3,4)
b = numpy.arange(20).reshape(4,5).T + 10

a_rownames = numpy.array(["m1", "m2", "m3"])
b_rownames = numpy.array(["m1", "m2", "m1", "m3", "m2"])

_, b_rows = numpy.where(a_rownames == b_rownames[:, numpy.newaxis])

b[:, columns_ids] = a[:, columns_ids][b_rows]

b
#>>> array([[10,  1, 20,  3],
#>>>        [11,  5, 21,  7],
#>>>        [12,  1, 22,  3],
#>>>        [13,  9, 23, 11],
#>>>        [14,  5, 24,  7]])

这一魔法有三个步骤:

_, b_rows = numpy.where(a_rownames == b_rownames[:, numpy.newaxis])
首先,我们生成两个垂直阵列:

a_rownames
#>>> array(['m1', 'm2', 'm3'],
#>>>       dtype='<U2')

b_rownames[:, numpy.newaxis]
#>>> array([['m1'],
#>>>        ['m2'],
#>>>        ['m1'],
#>>>        ['m3'],
#>>>        ['m2']],
#>>>       dtype='<U2')
numpy。其中
给出了
xs
ys
对该数组进行索引,以获得所有
真值。我们只对
ys
感兴趣,因此忽略
xs

_, b_rows = numpy.where(a_rownames == b_rownames[:, numpy.newaxis])

另一个魔法:

b[:, columns_ids] = a[:, columns_ids][b_rows]
需要了解两种不同类型的索引:

  • 使用布尔数组进行索引会过滤数组

  • 使用整数数组进行索引将获取这些索引处的行

索引式

array[xs]

(由于广播原因,它们是相同的)将为您提供根据上述规则匹配的所有索引,并在第一个轴中过滤

使用

将在第二个轴中过滤

所以首先我们过滤列(第二个轴)

然后我们过滤
a
(第一个轴)上的行:

它们现在是相同的形状,因此可以执行切片指定:

b[:, columns_ids] = a[:, columns_ids][b_rows]

或者生成一个新数组而不在b中过度写入原始数组:

np.where(column_ids[None,:], a[row_ids], b)

其中,列ID和行ID也是数组,如另一个答案中所示。

或要生成新数组而不在b中过度写入原始数组:

np.where(column_ids[None,:], a[row_ids], b)

其中,列ID和行ID也是数组,如另一个答案所示。

请注意,实际上不需要命名列来完成此操作,但numpy支持命名列(请参阅文档中的数据类型)pandas的dataframe专门用来反映您在R中使用的情况。我查看了pandas的
description,它看起来像是我需要轻松地从R迁移到Python世界的东西。谢谢你指点我!但是,如果numpy可以做到这一点,这也很好。请注意,您实际上不需要命名列来实现这一点,但numpy确实支持命名列(请参阅文档中的数据类型)pandas的dataframe专门用来反映您在R中使用的情况。我查看了pandas的
description,它看起来像是我需要轻松地从R迁移到Python世界的东西。谢谢你指点我!但是如果这可以用numpy实现,这也会很好。这也是一个非常好而且非常简短的解决方案!但是使用
None
创建newaxis的原因是什么?即使使用
np,它也可以正常工作。其中(列id,a[b\u行],b)
我发现明确表示正在处理的数组的维度非常有用。这也是一个非常好而且非常简短的解决方案!但是使用
None
创建newaxis的原因是什么?即使使用
np,它也可以正常工作。其中(列id,a[b\u行],b)
我发现明确表示正在处理的数组的维度很有用。