迭代3D numpy数组并计算每个序列的百分比变化

时间:2018-02-05 22:59:50

标签: python arrays numpy

我在迭代,广播以及通常制作循环代码方面存在巨大差距。

我有一组大小的序列(2000,10,200)。我想采用每个(10,200)序列并将所有10行除以该序列的第一行,以获得相对于单个窗口的百分比变化。

此外,我只想对200总数的前100个元素执行除法运算。

使用传统for循环的伪代码:

#Loop over each of the 2000 sequences
#Loop over each of the 10 rows
#Divide each row (first 100 elements) by the the first row-1 (first 100 elements) and save

这是我的尝试,虽然它不起作用,可能不是正确的方法。对代码的任何解释都非常感谢。

for sequence in data:
    for row in data[0][row]:
        data[0][row]  = data[0][row][0:99] / data[0][0][0:99] -1

1 个答案:

答案 0 :(得分:2)

<强>设置
让我们看一个较小的例子:

data = np.arange(72).reshape(3, 4, 6) + 10
data

array([[[10, 11, 12, 13, 14, 15],
        [16, 17, 18, 19, 20, 21],
        [22, 23, 24, 25, 26, 27],
        [28, 29, 30, 31, 32, 33]],

       [[34, 35, 36, 37, 38, 39],
        [40, 41, 42, 43, 44, 45],
        [46, 47, 48, 49, 50, 51],
        [52, 53, 54, 55, 56, 57]],

       [[58, 59, 60, 61, 62, 63],
        [64, 65, 66, 67, 68, 69],
        [70, 71, 72, 73, 74, 75],
        [76, 77, 78, 79, 80, 81]]])

<强>解决方案
首先确定要分割的最后一个维度的数量

half_last_dim = data.shape[-1] // 2

其次,使用长度为一的数组切割第二维以保持维度并启用广播

data[:, :, :half_last_dim] / data[:, [0], :half_last_dim]

array([[[ 1.        ,  1.        ,  1.        ],
        [ 1.6       ,  1.54545455,  1.5       ],
        [ 2.2       ,  2.09090909,  2.        ],
        [ 2.8       ,  2.63636364,  2.5       ]],

       [[ 1.        ,  1.        ,  1.        ],
        [ 1.17647059,  1.17142857,  1.16666667],
        [ 1.35294118,  1.34285714,  1.33333333],
        [ 1.52941176,  1.51428571,  1.5       ]],

       [[ 1.        ,  1.        ,  1.        ],
        [ 1.10344828,  1.10169492,  1.1       ],
        [ 1.20689655,  1.20338983,  1.2       ],
        [ 1.31034483,  1.30508475,  1.3       ]]])

回到data
使data类型为float

# Only necessary because my example started with integers.
data = data.astype(float)

data[:, :, :half_last_dim] /= data[:, [0], :half_last_dim]
data.round(2)  # rounded for pretty printing

array([[[  1.  ,   1.  ,   1.  ,  13.  ,  14.  ,  15.  ],
        [  1.6 ,   1.55,   1.5 ,  19.  ,  20.  ,  21.  ],
        [  2.2 ,   2.09,   2.  ,  25.  ,  26.  ,  27.  ],
        [  2.8 ,   2.64,   2.5 ,  31.  ,  32.  ,  33.  ]],

       [[  1.  ,   1.  ,   1.  ,  37.  ,  38.  ,  39.  ],
        [  1.18,   1.17,   1.17,  43.  ,  44.  ,  45.  ],
        [  1.35,   1.34,   1.33,  49.  ,  50.  ,  51.  ],
        [  1.53,   1.51,   1.5 ,  55.  ,  56.  ,  57.  ]],

       [[  1.  ,   1.  ,   1.  ,  61.  ,  62.  ,  63.  ],
        [  1.1 ,   1.1 ,   1.1 ,  67.  ,  68.  ,  69.  ],
        [  1.21,   1.2 ,   1.2 ,  73.  ,  74.  ,  75.  ],
        [  1.31,   1.31,   1.3 ,  79.  ,  80.  ,  81.  ]]])

更多解释
See Broadcasting Rules
为了使广播正确,我们希望我们广播的内容与所有尺寸的尺寸相匹配,除了我们定位的尺寸。对于该维度,我们需要长度1

data.shape
(3, 4, 6)

data[:, [0], :].shape
(3, 1, 6)