如何使用高级布尔索引在numpy中分配值?

时间:2018-12-09 06:26:09

标签: python-3.x numpy numpy-broadcasting

我正在尝试使用布尔索引将一维输出广播到三维数组。我有一个要分配给的数组:

public function Page() {
 $this->load->view('layouts/topmenu.php', $metaData);
 $this->load->view("file.html");
 $this->load->view('layouts/bottom');
 $this->load->view('layouts/footer');
 }

然后是我用来建立索引的一组布尔数组:

output_array = np.zeros((2,4,3))

通过这些,我可以构造一个三维布尔索引数组,并使用它为输出数组分配一个值:

dim0_bool = np.array([True, True])
dim0_dim1_bool = np.array([[True, True, True, False],
                           [False, True, True, True]])
dim0_dim2_bool = np.array([[True, True, False],
                           [False, True, True]])

一切正常,并给出预期的输出:

output_array_idx = np.einsum('i, ij, ik -> ijk',
                            dim0_bool,
                            dim0_dim1_bool, 
                            dim0_dim2_bool)
output_array[output_array_idx] = 1.0

不过,我真正想做的是(而且我不确定这样做是否可行)是将一维数组广播到array([[[1., 1., 0.], [1., 1., 0.], [1., 1., 0.], [0., 0., 0.]], [[0., 0., 0.], [0., 1., 1.], [0., 1., 1.], [0., 1., 1.]]]) 的索引元素中。例如:

output_array

然后:

dim2_output = np.array([1.0, 2.0])

理想情况下会给出:

output_array[output_array_idx] = dim2_output

这不能按原样工作,因为用array([[[1., 2., 0.], [1., 2., 0.], [1., 2., 0.], [0., 0., 0.]], [[0., 0., 0.], [0., 1., 2.], [0., 1., 2.], [0., 1., 2.]]]) 索引output_array会将其缩小为一维数组,因此我无法分配output_array_idx(尺寸,但长度不同)。

希望如此,希望得到大家的帮助(或关于如何更好地解决此问题的建议)。

2 个答案:

答案 0 :(得分:1)

您可以构造一个大小匹配的[1,2,1,2,...]数组。

np.resize执行正确的复制:

In [741]: np.resize([1,2],12)
Out[741]: array([1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2])

repeat

In [744]: np.array([[1,2]]).repeat(6,axis=0).ravel()
Out[744]: array([1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2])

答案 1 :(得分:1)

这是一个很肮脏的方法。您可以设置output_array以包含dim2_output索引。缺点是output_array不再符合其名称,您需要制作两个副本-一个用于索引,一个用于结果。

策略是初始化nans的数组,根据您的布尔掩码和我们的np.nancumsum填充数组以恢复索引。

import numpy as np

# init output array with nans instead of zeros
output_array = np.full((2, 4, 3), np.nan)

dim0_bool = np.array([True, True])
dim0_dim1_bool = np.array([[True, True, True, False], [False, True, True, True]])
dim0_dim2_bool = np.array([[True, True, False], [False, True, True]])


output_array_idx = np.einsum(
    "i, ij, ik -> ijk", dim0_bool, dim0_dim1_bool, dim0_dim2_bool
)

# make the output array contain indices for dim2_output
output_array[output_array_idx] = 1
output_array = (np.nancumsum(output_array, -1) - 1) * output_array
output_array[np.isnan(output_array)] = -1

# append to work with index manipulations 0
dim2_output = np.array([1.0, 2.0, 0])

result = dim2_output[output_array.astype(np.int)]


# array([[[1., 2., 0.],
# [1., 2., 0.],
# [1., 2., 0.],
# [0., 0., 0.]],

# [[0., 0., 0.],
# [0., 1., 2.],
# [0., 1., 2.],
# [0., 1., 2.]]])