微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在给定行索引和起始列索引的情况下为numpy数组赋值?

如何解决如何在给定行索引和起始列索引的情况下为numpy数组赋值?

a = np.array([2,3,1,4])
b = np.array([2,7,1])
c = np.zeros((4,10))

我想为1中的某些元素分配值cab定义了此类元素的位置。 a是每一行中值1的起始列索引。 b代表该行中有多少连续的1。我期望的输出是:

array([[ 0.,0.,1.,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索引来做到这一点?谢谢。

解决方法

您可以将其投放到一维问题中

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,c.shape)

c.ravel()[to_take] = 1

在上面的代码中,convert_indsab转换为

array([ 2,3,13,14,15,21,22,23,24,25,26,27,34])

是扁平化1c的索引。这样,您只需要遍历函数b中的convert_inds

,

我实现了下一个解决方案,没有任何Python循环,只有纯NumPy代码。也许它不像python循环解决方案那么简单,但是肯定会更快,特别是对于大数据。

Try it online!

import numpy as np

def 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] = val

a = np.array([2,1,4])
b = np.array([2,7,1])
c = np.zeros((4,10))

set_val_2d(c,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.]]
,

如果您选择基于花式索引的方法,则最困难的部分是查找轴1的索引。这非常类似于:

>>> np.repeat(a,b)
array([2,2,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,4,5,6,4],dtype=int32)

毕竟,您可以完成它:

c[np.repeat(np.arange(len(c)),b),accumulative_count(b,a)] = 1

c:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。