如何解决如何在给定行索引和起始列索引的情况下为numpy数组赋值?
a = np.array([2,3,1,4])
b = np.array([2,7,1])
c = np.zeros((4,10))
我想为1
中的某些元素分配值c
。 a
和b
定义了此类元素的位置。 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_inds
将a
和b
转换为
array([ 2,3,13,14,15,21,22,23,24,25,26,27,34])
是扁平化1
中c
的索引。这样,您只需要遍历函数b
中的convert_inds
。
我实现了下一个解决方案,没有任何Python循环,只有纯NumPy代码。也许它不像python循环解决方案那么简单,但是肯定会更快,特别是对于大数据。
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 举报,一经查实,本站将立刻删除。