【问题标题】:numpy "extend/append" ndarraynumpy“扩展/追加”ndarray
【发布时间】:2018-06-02 19:04:15
【问题描述】:

问题:

我有一个 numpy 数组

tf = numpy.full((500, 4, 1, 2), [500, 1])

tf : 
array([[[[ 500.,    1.]],

    [[ 500.,    1.]],

    [[ 500.,    1.]],

    [[ 500.,    1.]]],

   ..., 
   [[[ 500.,    1.]],

    [[ 500.,    1.]],

    [[ 500.,    1.]],

    [[ 500.,    1.]]]])


tf.shape :
(500, 4, 1, 2)

考虑第一组: tf[0][0]这是:array([[ 500., 1.]])

我需要能够附加(就地)附加值,例如 [[100, 0.33], [1, 0.34], [15, 0.33]],以便最终结果看起来像(对每个元素执行此操作):

tf : 
array([[[[ 500.,  1.], [100.,  0.33], [1.,  0.34], [15.,   0.33]],

    [[ 500.,    1.]],

    [[ 500.,    1.]],

    [[ 500.,    1.]]],

   ..., 
   [[[ 500.,    1.]],

    [[ 500.,    1.]],

    [[ 500.,    1.]],

    [[ 500.,    1.]]]])

我试过numpy.concatenate((tf[0][0], [[100, 0.33]]), axis = 0) 这会返回一个新的附加ndarray,但我无法将它分配回tf[0][0],因为它失败并出现以下错误。 ValueError: could not broadcast input array from shape (2,2) into shape (1,2)

还有其他方法可以使用 numpy 实现我想要的吗?

================================================ ===========

效率低下的list 做法:

# initialization
tf = [[[]] for i in xrange(500)]
for i in xrange(500):
    tf[i] = [[] for a in xrange(4)]
    for j in xrange(4):
        tf[i][j].append([500, 1.0])

# usage: (for any 0 < i < 500; 0 < j < 4 )

tf[i][j].append([100, 0.33])

但这是低效的(考虑到我需要这样做超过一百万次)

【问题讨论】:

  • 你不能使用numpy.ndarrays 来做到这一点,这是真正的、固定大小的多维数组。执行此操作的有效方法是使用列表。
  • @juanpa.arrivillaga this operation is carried out for each of the elements - 所以看起来它不会是一个参差不齐的数组,而是一个普通的数组。
  • 一个后续问题,然后是,如何有效地将这个嵌套列表转换为 ndarray 以进行进一步处理?
  • @Divakar 也许,OP 可以详细说明。
  • @okkhoy 转换为ndarray 你唯一的选择是使用某种dtype=object 数组,这基本上是一个坏列表。您在什么意义上的“低效”是指“低效的列表方式”?

标签: python arrays numpy append


【解决方案1】:

您的方法中的问题是每个元素的形状各不相同,因此您不能拥有固定的形状。但是,您可以将每个元素定义为类型 object 并实现您想要做的事情。

import numpy as np

tf = np.empty((500, 4, 1), dtype= object)

会产生

array([[[None],
        [None],
        [None],
        [None]],

       [[None],
        [None],
        [None],
        [None]],

       [[None],
        [None],
        [None],
        [None]],

       ...,
       [[None],
        [None],
        [None],
        [None]],

       [[None],
        [None],
        [None],
        [None]],

       [[None],
        [None],
        [None],
        [None]]], dtype=object)

现在将常量初始元素作为列表添加到每个数组元素中。您可能很想在这里使用fill(),但这会为每个数组元素分配一个对象,并且修改单个数组元素会改变整个数组。要进行初始化,您无法避免遍历整个数组。

for i,v in enumerate(tf):
    for j,w in enumerate(v):
        tf[i][j][0] = [[500.0,1.0]]

会产生

array([[[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       ...,
       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]]], dtype=object) 

现在您可以分别访问每个元素。根据需要使用附加或扩展。

 tf[0][0][0].append([100,0.33])

会给

array([[[list([[500.0, 1.0], [100, 0.33]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       ...,
       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]],

       [[list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])],
        [list([[500.0, 1.0]])]]], dtype=object)

只有初始化需要遍历数组。

【讨论】:

  • 我有一个后续问题,我可以稍后将其用作普通的 numpy 数组吗?例如,做数组乘法、点积等?
  • 我没听懂。你能解释一下吗?
  • 对不起!我的意思是:最深的数据类型是 list ,所以想知道我是否可以使用 numpy 操作,如点、ndarray 乘法等,
  • 这取决于操作。我建议在添加所有必需元素后,您可以遍历数组并将每个单独的列表转换为 numpy 数组。这样标量操作和其他一些数组范围的操作应该可以工作。
  • @okkhoy,对象 dtype 数组的数学运算是命中注定的。有些传播到对象,有些则不传播。所有这些都将比使用常规数组慢。索引可能比列表慢。先测试小案例。
猜你喜欢
  • 2012-09-21
  • 1970-01-01
  • 2013-01-04
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 2019-01-11
  • 2017-01-02
  • 2019-05-03
相关资源
最近更新 更多