给定行索引和起始列索引,如何将值分配给 numpy 数组?

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

b = np.array([2,3,7,1])

c = np.zeros((4, 10))


1我想为 中的某些元素赋值c。a并b定义这些元素的位置。是每行中a值的起始列索引。1并表示该行有b多少个连续的。1我期望的输出是:


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

       [ 0.,  0.,  0.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],

       [ 0.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  0.,  0.],

       [ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.]])

我可以使用一个简单的 for 循环,如下所示:


for i in range(c.shape[0]):

    for k in range(a[i], a[i]+b[i]):

        c[i,k]=1

但对于大型数组来说会很慢,有没有更快的 numpy 索引来做到这一点?谢谢。


翻过高山走不出你
浏览 112回答 3
3回答

慕标琳琳

您可以将其转化为一维问题def convert_inds(a,b,array_shape):        nrows,ncols = array_shape    to_take = np.zeros(sum(b))    count = 0    for ind,item in enumerate(b):        start_ind = ind*ncols+a[ind]        to_take[count:count+item] = np.arange(start_ind,start_ind+item)        count += item            return to_take.astype(np.int)to_take = convert_inds(a,b,c.shape)c.ravel()[to_take] = 1在上面的代码中,convert_inds将a和转换b为array([ 2,  3, 13, 14, 15, 21, 22, 23, 24, 25, 26, 27, 34])它们是1展平后 s的索引c。通过这样做,您只需要b在函数中进行迭代即可convert_inds。

LEATH

我实现了下一个解决方案,没有任何 Python 循环,只有纯 NumPy 代码。也许它不像 python-loop 解决方案那么简单,但肯定会快得多,特别是对于大数据。在线尝试一下!import numpy as npdef set_val_2d(a, val, starts, lens):    begs = starts + np.arange(a.shape[0]) * a.shape[1]    ends = begs + lens    clens = lens.cumsum()    ix = np.ones((clens[-1],), dtype = np.int64)    ix[0] = begs[0]    ix[clens[:-1]] = begs[1:] - ends[:-1] + 1    ix = ix.cumsum()    a.ravel()[ix] = vala = np.array([2,3,1,4])b = np.array([2,3,7,1])c = np.zeros((4, 10))set_val_2d(c, 1, a, b)print(c)输出:[[0. 0. 1. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 1. 1. 0. 0. 0. 0.] [0. 1. 1. 1. 1. 1. 1. 1. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]]

慕侠2389804

如果您选择基于索引的奇特方法,最困难的部分是查找轴 1 的索引。这非常类似于:>>> np.repeat(a, b)array([2, 2, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 4])除了每组索引应该递增之外。可以使用以下函数完成此修复:def accumulative_count(counts, initial):    counter = np.ones(np.sum(counts), dtype=int)    marker_idx = np.r_[0, np.cumsum(counts)[:-1]]    subtract_vals = np.r_[1, counts[:-1]]    initial_vals = np.r_[initial[0], np.diff(initial)]    counter[marker_idx] = counter[marker_idx] - subtract_vals + initial_vals    return np.cumsum(counter)>>> accumulative_count(counts, initial)array([2, 3, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 4], dtype=int32)毕竟,你有能力完成它:c[np.repeat(np.arange(len(c)), b), accumulative_count(b, a)] = 1c:array([[0., 0., 1., 1., 0., 0., 0., 0., 0., 0.],       [0., 0., 0., 1., 1., 1., 0., 0., 0., 0.],       [0., 1., 1., 1., 1., 1., 1., 1., 0., 0.],       [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.]])
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python