Python 从一维NumPy阵列创建二维遮罩

Python 从一维NumPy阵列创建二维遮罩,python,numpy,Python,Numpy,我想从numpy数组中的行中获取第一个n值,其中n在单独的一维数组中指定: import numpy as np a = np.zeros((5, 5)) n = [1, 3, 2, 4, 1] result = [[1, 0, 0, 0, 0], [1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 1, 1, 1, 0], [1, 0, 0, 0, 0]] 我正在寻找一种不需要迭代的解

我想从numpy数组中的行中获取第一个n值,其中n在单独的一维数组中指定:

import numpy as np

a = np.zeros((5, 5))
n = [1, 3, 2, 4, 1]

result = [[1, 0, 0, 0, 0],
          [1, 1, 1, 0, 0],
          [1, 1, 0, 0, 0],
          [1, 1, 1, 1, 0],
          [1, 0, 0, 0, 0]]

我正在寻找一种不需要迭代的解决方案,因为结果数组将有数百万行。

我想您正在尝试获得类似的结果?我不知道可能有一种特定于numpy的方法速度更快,但如果速度不是问题,这就足够了:

import numpy as np

a = np.zeros((5, 5))
n = [1, 3, 2, 4, 1]

for index in range(len(n)):
    a[index][0:n[index]] = 1

print(a)
输出

[[1.0.0.0.0] [1. 1. 1. 0. 0.] [1. 1. 0. 0. 0.] [1. 1. 1. 1. 0.] [1.0.0.0.0.]]


我想你是想得到这样的东西?我不知道可能有一种特定于numpy的方法速度更快,但如果速度不是问题,这就足够了:

import numpy as np

a = np.zeros((5, 5))
n = [1, 3, 2, 4, 1]

for index in range(len(n)):
    a[index][0:n[index]] = 1

print(a)
输出

[[1.0.0.0.0] [1. 1. 1. 0. 0.] [1. 1. 0. 0. 0.] [1. 1. 1. 1. 0.] [1.0.0.0.0.]]

利用n与范围数组的外部比较来创建掩码,从而创建最终数组-

ncols = 5
mask_out = np.greater.outer(n,np.arange(ncols))
样本运行-

In [19]: n = [1, 3, 2, 4, 1]

In [9]: ncols = 5

# Output as mask
In [10]: np.greater.outer(n,np.arange(ncols))
Out[10]: 
array([[ True, False, False, False, False],
       [ True,  True,  True, False, False],
       [ True,  True, False, False, False],
       [ True,  True,  True,  True, False],
       [ True, False, False, False, False]])

# Output as array of 0s and 1s
In [11]: np.greater.outer(n,np.arange(ncols)).view('i1')
Out[11]: 
array([[1, 0, 0, 0, 0],
       [1, 1, 1, 0, 0],
       [1, 1, 0, 0, 0],
       [1, 1, 1, 1, 0],
       [1, 0, 0, 0, 0]], dtype=int8)
如果必须填充已初始化的数组结果,只需使用mask_out来屏蔽数组,即result[mask_out]=..

在创建掩码和最终数组时,使用n与范围数组的外部比较-

ncols = 5
mask_out = np.greater.outer(n,np.arange(ncols))
样本运行-

In [19]: n = [1, 3, 2, 4, 1]

In [9]: ncols = 5

# Output as mask
In [10]: np.greater.outer(n,np.arange(ncols))
Out[10]: 
array([[ True, False, False, False, False],
       [ True,  True,  True, False, False],
       [ True,  True, False, False, False],
       [ True,  True,  True,  True, False],
       [ True, False, False, False, False]])

# Output as array of 0s and 1s
In [11]: np.greater.outer(n,np.arange(ncols)).view('i1')
Out[11]: 
array([[1, 0, 0, 0, 0],
       [1, 1, 1, 0, 0],
       [1, 1, 0, 0, 0],
       [1, 1, 1, 1, 0],
       [1, 0, 0, 0, 0]], dtype=int8)

如果必须填充已初始化的数组结果,只需使用mask_out来屏蔽该数组,即result[mask_out]=..

以下是一种使用高级索引到模板行数组的方法:

def f_pp(a, ncol=None):
    if ncol is None:
        ncol = a.max()
    t = np.array([1, 0], 'u1').repeat(ncol)
    ts, = t.strides
    t = np.lib.stride_tricks.as_strided(t[ncol:], (ncol+1, ncol), (-ts, ts))
    return t[a]
使用@Divakar作为参考的计时:

def f_div(a, ncol=None):
    if ncol is None:
        ncol = a.max()
    return np.greater.outer(a, np.arange(ncol))

from timeit import timeit

for ncol, nrow in [(10, 10**7), (100, 10**6), (1000, 10**5), (10000, 10000)]:
    a = np.random.randint(0, ncol+1, nrow)
    print('\n', ncol, nrow, ':')
    print('div', timeit(lambda: f_div(a), number=10))
    print('pp ', timeit(lambda: f_pp(a), number=10))
印刷品:

 10 10000000 :
div 2.4297873955219984
pp  1.698299034498632

 100 1000000 :
div 1.465646200813353
pp  0.4803247870877385

 1000 100000 :
div 1.3471891237422824
pp  0.35979613568633795

 10000 10000 :
div 0.6783521044999361
pp  0.38309483136981726

以下是一种使用高级索引到模板行数组中的方法:

def f_pp(a, ncol=None):
    if ncol is None:
        ncol = a.max()
    t = np.array([1, 0], 'u1').repeat(ncol)
    ts, = t.strides
    t = np.lib.stride_tricks.as_strided(t[ncol:], (ncol+1, ncol), (-ts, ts))
    return t[a]
使用@Divakar作为参考的计时:

def f_div(a, ncol=None):
    if ncol is None:
        ncol = a.max()
    return np.greater.outer(a, np.arange(ncol))

from timeit import timeit

for ncol, nrow in [(10, 10**7), (100, 10**6), (1000, 10**5), (10000, 10000)]:
    a = np.random.randint(0, ncol+1, nrow)
    print('\n', ncol, nrow, ':')
    print('div', timeit(lambda: f_div(a), number=10))
    print('pp ', timeit(lambda: f_pp(a), number=10))
印刷品:

 10 10000000 :
div 2.4297873955219984
pp  1.698299034498632

 100 1000000 :
div 1.465646200813353
pp  0.4803247870877385

 1000 100000 :
div 1.3471891237422824
pp  0.35979613568633795

 10000 10000 :
div 0.6783521044999361
pp  0.38309483136981726

是的,我处理的数据实际上相当大,所以我希望找到一个numpy方法。我将更新我的问题以反映这一点。是的,我正在处理的数据实际上相当大,所以我希望找到一种numpy方法。我将更新我的问题以反映这一点。