在循环中附加具有不同维度的numpy ndarray

Posted

技术标签:

【中文标题】在循环中附加具有不同维度的numpy ndarray【英文标题】:Append numpy ndarrays with different dimensions in loop 【发布时间】:2013-12-24 18:26:31 【问题描述】:

我需要附加在每个循环中创建的数组,以便最后得到一个 ndarray。代码结构是这样的:

for...:
      .
      .
      .
     for...:
         list1 = array([some_math_here])
         list2.append(list1)

     #each loop creats a list, converting it to array() gives different shaped arrays:
     array(list2).shape
     (2939, 4)
     (2942, 4)
     (2027, 4)
     (2030, 4)

     #list3 collects all the generated results
     list3.append(list2)

问: 如何使用n*4 列和不同行数的数组而不是 list3?

我尝试创建一个空数组a = array([0.,1.]) 然后append(a,array(list_2)) 但不起作用。我知道hstack vstack 等,但不能在循环中将它们与append 一起使用。有什么建议吗?

更新 以下是建议方法输出的实际代码:

files_ = glob.glob('D:\Test files\*.txt')
tfile_ = loadtxt('times.txt')    
averages_, d = [], []

with open ('outfile.csv', 'wb') as outfile:
    writer = csv.writer(outfile)

    for fcount_, fname_ in enumerate(files_):   
        data = loadtxt(fname_ , usecols = (1,2,3,4))    
        average_, fcol = [], []
        seg_len = 3

        for x in range(0, len(data[:,0]), seg_len):
            sample_means = [mean(data[x:x+seg_len,i]) for i in range(4)]
            none_zeros = [x if x >= 0 else x == 0 for x in sample_means]            
            average_.append(none_zeros)

        fcol = cumsum(array(average_)[:,0])
        average_ = array([row + [col] for row, col in zip(average_, fcol)])
        averages_.append(average_)
    d = concatenate(array(averages_))    
    df = pd.DataFrame(d)
    df.to_csv('pdtest2.csv')

输出:

           0         1         2         3         4
0   0.037039  0.103792  0.136116  0.579297  0.037039
1   0.051183  0.104669  0.177728  0.593771  0.088222
2   0.059517  0.105437  0.174274  0.571402  0.147739
3   0.053212  0.102476  0.167530  0.645745  0.200950
4   0.054637  0.104450  0.165228  0.596622  0.054637
5   0.051622  0.101161  0.166708  0.595964  0.106259
6   0.057324  0.099077  0.168024  0.596841  0.163583
7   0.054692  0.103573  0.157168  0.598596  0.218275
8   0.066699  0.100612  0.145984  0.591578  0.284974
9   0.120866  5.527104  4.678589  2.401020  0.120866
10  0.113958  5.176220  4.669872  2.361985  0.234824
11  0.121469  4.879613  4.659017  2.359573  0.356293
12  0.122511  4.695618  4.642240  2.363959  0.478803
13  0.126650  4.621933  4.620447  2.347073  0.605453
14  0.132708  4.676868  4.517568  2.364617  0.132708
15  0.125087  4.693535  4.459672  2.381941  0.257795
16  0.132708  4.715246  4.444705  2.334353  0.390503
17  0.133476  4.745619  4.406300  2.317467  0.523979

当我想要的时候:

    0           1           2           3           4           5           6           7           8           9           10          11          12          13          14          15          16          17          18          19
0   0.037038522 0.103792144 0.136115724 0.57929719  0.037038522 0.054637318 0.104450043 0.16522775  0.596621864 0.054637318 0.12086581  5.527104488 4.678589189 2.401020431 0.12086581  0.132707991 4.67686799  4.517567512 2.364616645 0.132707991
1   0.051183348 0.104669343 0.177727829 0.593770968 0.08822187  0.051621948 0.101160549 0.166708023 0.595963965 0.106259265 0.113957871 5.176219782 4.669871979 2.361985046 0.234823681 0.125087328 4.693534961 4.459672089 2.381941338 0.257795319
2   0.059516735 0.105436892 0.17427386  0.571402402 0.147738605 0.057323738 0.099077202 0.168023821 0.596841163 0.163583003 0.121468884 4.879613015 4.659016582 2.359572747 0.356292565 0.132707991 4.715245885 4.444704808 2.334353258 0.39050331
3   0.05321187  0.102476346 0.167530397 0.645744989 0.200950475 0.054692143 0.103572845 0.157168489 0.598595561 0.218275146 0.122510557 4.695618334 4.642240062 2.363958746 0.478803122 0.13347554  4.745619253 4.406299754 2.317467166 0.52397885
4   0           0           0           0           0           0.066698797 0.1006123   0.145984208 0.591577971 0.284973943 0.126649838 4.621932787 4.620447035 2.347072653 0.60545296  0           0            0          0           0

【问题讨论】:

这是一个有效的 Python 语法吗? 你不能完全得到你要找的东西,你要找的东西可能不是你想要的。所有这些 something-by-4 数组代表什么?您确定不想垂直堆叠而不是水平堆叠吗?您真的需要for 循环吗,或者如果没有它,您是否可以使用矢量化操作来生成更清洁、更快的代码? @user2357112,“垂直堆叠”是我想要的,我认为当每个数组有 4 列时,我说一个数组有 n*4 列,我的意思是,是吗?我已经使用 Python 仅 2 周了,当然我的代码不是最有效的代码,但由于需要几个 txt 文件对每个列进行一些数学运算,所以我有循环。 正如@CT 所说,您不能拥有形状不均匀的阵列。为了解决这个问题,您可以使用np.nan0 填充较短数组的末尾,或者使用掩码数组。堆叠的方法是通过循环将数组附加到 list 中,然后在结束时在 list 上调用 np.column_stacknp.hstack循环,不要np.append 循环内的数组。 【参考方案1】:

不,如果每列的n 不同,则不能创建n*4 2d array

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

Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    np.vstack((np.arange(10),np.arange(0,11),np.arange(0,12)))
  File "C:\Python27\lib\site-packages\numpy\core\shape_base.py", line 226, in vstack
    return _nx.concatenate(map(atleast_2d,tup),0)
ValueError: all the input array dimensions except for the concatenation axis must match exactly

查看ValueError,当每个array的维度不同时。

对于list3,您要么必须留在list,要么将每个list2 填充到相等的长度。

对于更高维度,同样的规则适用:np.vstack((np.ones((10,4)),np.ones((10,6)),np.ones((10,6)))) 不起作用,但np.vstack((np.ones((10,4)),np.ones((11,4)),np.ones((12,4)))) 将创建一个 35*4 array

在你的情况下,如果你 vstack 你的 list2s,你会得到一个 9938*4 array,如果这是你想要的。 (我没有得到 不同的行数 部分)

编辑:

要填充较短的arrays,以便每个array 具有相同的shape,您需要:np.lib.pad

>>> b=np.random.randint(0,20, size=(12,4))
>>> np.lib.pad(b, ((0,3),(0,0)), 'constant', constant_values=[0.])
array([[ 5,  2, 10,  7],
       [ 7, 17,  8, 11],
       [ 7,  7,  2, 10],
       [16, 17, 15, 16],
       [ 0, 19,  5,  6],
       [18, 19, 18,  6],
       [ 2,  8, 11, 19],
       [ 3, 17, 18, 16],
       [10,  1, 12, 11],
       [ 0,  7,  1, 14],
       [ 7, 17,  8, 16],
       [12,  6,  3,  5],
       [ 0,  0,  0,  0],
       [ 0,  0,  0,  0],
       [ 0,  0,  0,  0]])

((0,3),(0,0)) 表示在第一个轴的末尾填充 3 个元素,在它的开头填充 0 个元素。此外,这意味着在第二轴上不填充任何内容。在您的情况下,您需要((0,max_length-length_of_current_array),(0,0))

然后您只需使用np.hstack 将它们全部堆叠起来。

但在我看来,您可能想要填充nan 而不是0.0. 可能是有意义的数据值。

【讨论】:

我认为@PyLearner 想要的是np.column_stack(或者在他们的情况下,np.hstack)你的答案是正确的,因为在给定他们的输入时不可能有一个统一的数组,但是你的例子是他们的转置。 @askewchan,是的,我怀疑是这样。但后来我注意到 OP 的评论“垂直堆叠”是我想要的。无论如何,想法将是相同的。干杯! 哈哈,没错。实际上,如果您还不知道它们的作用,我发现所有堆栈函数的名称可能会模棱两可。例如,vstack:垂直堆叠,还是垂直堆叠? 谢谢大家。似乎我与 vstack、hstack 混淆了......我的意思是每个循环中创建的 4 列存储在前 4 列旁边。我认为这意味着水平堆叠而不是垂直堆叠! zh,这有点令人困惑......,如果在循环中创建的 arrays 的形状为 (2939, 4) (2942, 4) (2027, 4)(2030, 4),则结果数组应该有(9938, 4) 的形状? @askewchan,完全同意,这很令人困惑。 R 让我很头疼,我认为 cbind()rbind()vstack()hstack()(当然还有 dstack())更直观。【参考方案2】:

我认为你想要的是制作一个 NumPy 数组的普通 Python 列表。每个数组将具有相同的列数和类型,但可能有不同的行数。所以你应该从简单的list3 = []开始,然后做list3.append(arr) N次。最后,如果您想要一个包含所有行的大型 NumPy 数组,只需执行 np.concatenate(list3) 即可将它们一次全部放在一起。这比尝试在循环中连接 NumPy 数组更有效。

【讨论】:

感谢约翰的帮助。

以上是关于在循环中附加具有不同维度的numpy ndarray的主要内容,如果未能解决你的问题,请参考以下文章

使用 numpy 堆叠具有一个不同维度的数组

交换numpy数组的维度

在进行矩阵工作时如何理解循环和额外 numpy 维度之间的权衡?

无法在嵌套循环中使用 pandas 附加更大的数据帧。如何更改为 numpy 向量化?

numpy 插入一个元素,保持数组维度的数量

连接/附加多个不同大小的垂直数组