簡體   English   中英

給定行索引和起始列索引,如何將值分配給 numpy 數組?

[英]how to assign values to numpy array given the row indices and starting column indices?

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

我想將值1分配給c中的某些元素。 ab定義了這些元素的位置。 a是每行中值為1的起始列索引。 b代表該行有多少個連續的1 我期待的 output 是:

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

但是對於大的 arrays 會很慢,有沒有更快的 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,b,c.shape)

c.ravel()[to_take] = 1

在上面的代碼中, convert_inds會將ab轉換為

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

這是扁平化c1的索引。 通過這樣做,您只需要遍歷 function convert_inds中的b

我在沒有任何 Python 循環的情況下實現了下一個解決方案,只是純 NumPy 代碼。 也許它不像 python-loop 解決方案那么簡單,但肯定會快得多,尤其是對於大數據。

在線試用!

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,3,1,4])
b = np.array([2,3,7,1])
c = np.zeros((4, 10))

set_val_2d(c, 1, a, b)
print(c)

Output:

[[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, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 4])

除了每組索引應該遞增。 可以使用此 function 完成此修復:

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)] = 1

c:

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.]])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM