我有以下稀疏结构来描述底层密集数组A
:
a = np.array([1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1])
b = np.array([1, 5, 2, 3])
每当a
更改值时, 1
都会包含A
。只要b
更改值,A
就会包含新值。也就是说,我的a
,b
示例产生以下数组:
A = np.array([1, 1, 1, 1, 1, 5, 5, 2, 2, 2, 3])
如果给出稀疏信息,我怎样才能有效地恢复A
?我对b
为n维时可扩展的解决方案特别感兴趣。
在2d中,我们会有相同的a
,但
bb = np.array([[1, 5, 2, 2], [2, -1, 0, 1]])
产生
AA = np.array([[1, 1, 1, 1, 1, 5, 5, 2, 2, 2, 3], [2, 2, 2, 2, 2, -1, -1, 0, 0, 0, 1]])
答案 0 :(得分:2)
非常简单,cumsum
。使用cumsum
获取 intervaled 索引,然后将其索引到数据数组中。
因此,对于1D
数据 -
idx = a.cumsum(-1)-1
out = b[idx]
2D
数据 -
out = bb[np.arange(bb.shape[0])[:,None],idx]
对于通用n-dim
数据,只需使用np.take
沿最后一个轴索引,从而覆盖通用n-dim
个案例,如此 -
np.take(b_ndarray,idx,axis=-1)
示例运行
In [80]: a # sparse array that defines the intervals/indices
Out[80]: array([1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1])
In [81]: b # 1D data array
Out[81]: array([1, 5, 2, 3])
In [82]: bb # 2D data array
Out[82]:
array([[ 1, 5, 2, 2],
[ 2, -1, 0, 1]])
In [93]: idx = a.cumsum(-1)-1 # Get the intervaled indices
In [94]: idx
Out[94]: array([0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3])
In [84]: np.take(b,idx,axis=-1) # output for 1D data
Out[84]: array([1, 1, 1, 1, 1, 5, 5, 2, 2, 2, 3])
In [85]: np.take(bb,idx,axis=-1) # output for 2D data
Out[85]:
array([[ 1, 1, 1, 1, 1, 5, 5, 2, 2, 2, 2],
[ 2, 2, 2, 2, 2, -1, -1, 0, 0, 0, 1]])
让我们测试一些随机3D
数据 -
In [89]: bbb = np.random.randint(-4,5,(2,3,4))
In [90]: bbb
Out[90]:
array([[[-1, 0, 0, 4],
[ 0, -1, 3, 1],
[ 1, -4, -3, 1]],
[[-1, -4, 1, -4],
[-3, -2, 0, -2],
[-4, -1, -2, -4]]])
In [91]: np.take(bbb,idx,axis=-1)
Out[91]:
array([[[-1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 4],
[ 0, 0, 0, 0, 0, -1, -1, 3, 3, 3, 1],
[ 1, 1, 1, 1, 1, -4, -4, -3, -3, -3, 1]],
[[-1, -1, -1, -1, -1, -4, -4, 1, 1, 1, -4],
[-3, -3, -3, -3, -3, -2, -2, 0, 0, 0, -2],
[-4, -4, -4, -4, -4, -1, -1, -2, -2, -2, -4]]])
运行时测试
其他方法 -
def diff_repeat_1d(a, b): # @Kasramvd's soln for 1D
inds = np.concatenate((np.where(a)[0], [a.size]))
durations = np.diff(inds)
return np.repeat(b, durations)
def diff_repeat_2d(a, b): # @Kasramvd's soln for 2D
inds = np.concatenate((np.where(a)[0], [a.size]))
durations = np.diff(inds)
return np.repeat(bb, durations, axis=1)
关于1D数据的计时 -
In [199]: a = np.array([1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1])
...: b = np.array([1, 5, 2, 3])
...:
In [200]: a = np.tile(a,100000)
...: b = np.tile(b,100000)
...:
In [201]: %timeit diff_repeat_1d(a, b) # @Kasramvd's soln
100 loops, best of 3: 8.42 ms per loop
In [202]: %timeit np.take(b,a.cumsum()-1,axis=-1)
100 loops, best of 3: 4.53 ms per loop
关于2D数据的计时 -
In [203]: bb = np.array([[1, 5, 2, 2], [2, -1, 0, 1]])
In [204]: bb = np.tile(bb,100000)
In [206]: %timeit diff_repeat_2d(a, bb) # @Kasramvd's soln
100 loops, best of 3: 12.1 ms per loop
In [207]: %timeit np.take(bb,a.cumsum()-1,axis=-1)
100 loops, best of 3: 5.58 ms per loop
答案 1 :(得分:1)
这是一种方式:
In [45]: inds = np.concatenate((np.where(a)[0], [a.size]))
In [46]: durations = np.diff(inds)
In [47]: np.repeat(b, durations)
Out[47]: array([1, 1, 1, 1, 1, 5, 5, 2, 2, 2, 3])
对于2D阵列,您只需将轴传递给repeat
函数:
In [49]: np.repeat(bb, durations, axis=1)
Out[49]:
array([[ 1, 1, 1, 1, 1, 5, 5, 2, 2, 2, 2],
[ 2, 2, 2, 2, 2, -1, -1, 0, 0, 0, 1]])