【问题标题】:How to add two columns of a numpy array?如何添加 numpy 数组的两列?
【发布时间】:2012-11-24 00:13:29
【问题描述】:

我有两个行数相同的 NumPy 数组,但我想添加特定的列。

我尝试了以下方法:

src_array[:, 3] += column_array_to_add[:, 0]

但是,这甚至不能解释。在NumPy 中执行此操作的正确方法是什么?我希望能够同时使用整数和字符串。

编辑:一个简短的、独立的测试脚本

import numpy
src = numpy.array([["a", "b"], ["c", "d"], ["e", "f"]])
src2 = numpy.array([["x"], ["y"], ["z"]])

src[:, 1] += src2[:, 0]
print src
exit()

此脚本返回以下错误:

src[:, 1] += src2[:, 0]
TypeError: unsupported operand type(s) for +=: 'numpy.ndarray' and 'numpy.ndarray'

【问题讨论】:

  • column_array_to_add 是另一个二维数组,还是一维列数组,顾名思义?如果是前者,那么问题肯定出在您没有向我们展示的代码中的其他地方,因为正如 Akavall 所演示的那样,该行是有效的。如果是后者,为什么要尝试将 2D 索引传递到 1D 数组中?
  • 不管怎样,给我们一个Short, Self Contained, Correct Example——也就是说,给我们足够的代码让我们自己运行它并查看错误。
  • @abarnert 完成,我很抱歉没有早点这样做。
  • src 的数据类型是'S1',这意味着数组中的每个字符串只有一个字节可用。这不能就地改变;一旦创建了 numpy 数组,就无法更改元素的大小。因此,您尝试做的事情将行不通。

标签: python numpy


【解决方案1】:

这样的东西有用吗?

import numpy as np

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

y = np.array([[5,6],[7,8]])

结果

>>> x
array([[1, 2],
       [3, 4]])
>>> y
array([[5, 6],
       [7, 8]])
>>> x[:,1] + y[:,1]
array([ 8, 12])
>>> x[:, 1] += y[:, 1] # using +=
>>> x[:, 1]
array([ 8, 12])

更新:

我认为这应该适合你:

src = np.array([["a", "b"], ["c", "d"], ["e", "f"]], dtype='|S8')
src2 = np.array([["x"], ["y"], ["z"]], dtype='|S8')

def add_columns(x, y):
    return [a + b for a,b in zip(x, y)]

def update_array(source_array, col_num, add_col):
    temp_col = add_columns(source_array[:, col_num], add_col)
    source_array[:, col_num] = temp_col  
    return source_array

结果:

>>> update_array(src, 1, src2[:,0])
array([['a', 'bx'],
       ['c', 'dy'],
       ['e', 'fz']], 
      dtype='|S8')

【讨论】:

  • +1,但我会将+ 更改为+= 以表明他的确切代码完全有效。
  • @Akavall 你确定这也适用于字符串吗?我在描述中添加了一个示例。谢谢
  • 我尝试使用numpy.add(),但它对我不起作用。根据这个问题的答案,字符串操作应该在纯python中完成:stackoverflow.com/questions/9958506/…
  • @Akavall 当然,但数据已经在 numpy 数组中,我无法控制。
  • @Jim:您总是可以将它从numpy 数组中复制到纯Python 中。这就像将其复制到具有不同固定长度字符串 dtype 的不同 numpy 数组一样简单。
【解决方案2】:

当您需要调试此类事情时,将其分解为更简单的步骤很有用。您是否弄错了切片,添加了两个不兼容的数组类型,添加了两种类型但试图将结果粘贴到不兼容的类型中(当+ 可以但= 不行时使用+=),或者添加不兼容的数据值?其中任何一个都可以提出TypeError,那么我们怎么知道你在做什么呢?

好吧,一次做,然后看看:

切片:

>>> src[:, 1]
array(['b', 'd', 'f'], dtype='|S1')
>>> src[:, 1] = ['x', 'y', 'z']
>>> src
>>> array([['a', 'x'], ['c', 'y'], ['e', 'z']], dtype='|S1')

没关系。添加呢?

>>> src + src2
TypeError: unsupported operand type(s) for +: 'numpy.ndarray' and 'numpy.ndarray'

因此,我们已经发现了与您的更复杂情况相同的错误,没有切片,也没有+=,这使得调试变得更加容易。让我们让它变得更简单:

>>> s1, s2 = np.array('a'), np.array('b')
>>> s1 + s2
TypeError: unsupported operand type(s) for +: 'numpy.ndarray' and 'numpy.ndarray'

所以即使添加两个 0D 数组也会失败!没有比这更简单的了。

也许是数据类型。如果我们使用整数会发生什么?

>>> n1, n2 = np.array(1), np.array(2)
>>> n1 + n2
3

你可以一直回到你原来的例子,使用整数而不是字符串,它仍然可以正常工作:

>>> m1 = np.array([[1,2], [3,4], [5,6]])
>>> m2 = np.array([[7], [8], [9]])
>>> m1[:, 1] += m2[:, 0]
>>> array([[ 1,  9],
           [ 3, 12],
           [ 5, 15]])

这应该很明显问题出在数据类型上。那么,的数据类型是什么?只需打印出数组,看看numpy 认为它是什么:

>>> src = numpy.array([["a", "b"], ["c", "d"], ["e", "f"]])
>>> src
array([['a', 'b'], ['c', 'd'], ['e', 'f']], dtype='|S1')

'|S1' 不是您在Data types 的用户指南部分看到的友好数据类型之一,它是一个结构定义,如Structured arrays 部分所述。意思是1个字符的固定长度字符串。

这使得问题显而易见:您不能添加两个 1 字符的固定长度字符串,因为结果不是 1 字符的固定长度字符串。

如果您真的想按原样工作,简单的解决方案是将它们保留为 Python 字符串:

>>> src = numpy.array([["a", "b"], ["c", "d"], ["e", "f"]], dtype=object)
>>> src2 = numpy.array([["x"], ["y"], ["z"]], dtype=object)    
>>> src[:, 1] += src2[:, 0]

没有更多TypeError

或者,如果你明确地给 src 一个 dtype |S2numpy 将允许这样做,第二个字符将是空白的。它不会让您在其中添加另一个 |S1,但您可以在 Python 中循环,或者找到一种复杂的方法来修复 numpy 为您执行此操作。当然,无论哪种方式,您都不会获得 numpy 的任何通常时间性能优势,但您仍然可以获得使用打包的固定大小单元的空间性能优势。

但您可能想退后一步,在此处询问您想从numpy 中得到什么。你在这里的实际更高层次的目标是什么? numpy 的大部分好处来自于使用严格的 C/Fortran 风格的数据类型,numpy 知道如何使用它们——它可以将它们紧密打包,无需额外取消引用(并且无需引用计数)即可访问它们,在在没有 Python 的任何帮助的情况下,以各种方式从乘法到复制到打印等。但它不能进行字符串操作。如果您尝试对字符串操作进行矢量化,则说明您使用了错误的库来执行此操作。如果您只是因为有人说它很快而使用numpy,那么,在很多情况下都是这样,但在这个情况下则不然。如果您使用 numpy 是因为其他代码正在向您提供 numpy 数据,但您不想以 numpy 的方式处理它,那么没有什么能阻止您将其转换为纯 Python 数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2021-07-16
    • 2010-12-26
    • 1970-01-01
    • 2014-03-05
    • 2022-01-24
    相关资源
    最近更新 更多