【问题标题】:Vector way of populating numpy array填充numpy数组的向量方式
【发布时间】:2019-07-23 09:22:59
【问题描述】:

我有一些二进制字符串s,比如001010。我想将它转换为 numpy 数组 a 其中 a[i] = np.array([[1], [0]]) 如果 s[i] == '0'np.array([[0], [1]]) 否则。

所以我写了这样的代码:

a = np.empty([len(s), 2, 1])
for i, char in enumerate(s):
    if char == '0':
        a[i] = np.array([[1], [0]])
    elif char == '1':
        a[i] = np.array([[0], [1]])

是否可以以更 numpy 的方式将其重写为没有 for 循环的向量化形式?

我的预期输出如下:

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

       [[1.],
        [0.]],

       [[0.],
        [1.]],

       [[1.],
        [0.]],

       [[0.],
        [1.]],

       [[1.],
        [0.]]])

【问题讨论】:

    标签: python arrays numpy vectorization


    【解决方案1】:

    方法#1:这是一个使用 NumPy 字符数组的方法 -

    sa = np.frombuffer(s,dtype='S1')
    out = np.where(sa[:,None,None]=='0',[[1],[0]],[[0],[1]])
    

    方法 #2: 一种作为单线 -

    ((np.frombuffer(s,dtype=np.uint8)[:,None]==[48,49])[...,None]).astype(float)
    

    方法#3:最后一个完全专注于性能 -

    a = np.zeros([len(s), 2, 1])
    idx = np.frombuffer(s,dtype=np.uint8)-48
    a[np.arange(len(idx)),idx] = 1
    

    100000 字符字符串的计时 -

    In [2]: np.random.seed(0)
    
    In [3]: s = ''.join(map(str,np.random.randint(0,2,(100000)).tolist()))
    
    # @yatu's soln
    In [4]: %%timeit
         ...: a = np.array(list(s), dtype=int)
         ...: np.where(a==0, np.array([[1], [0]]), np.array([[0], [1]])).T[:,:,None]
    10 loops, best of 3: 36.3 ms per loop
    
    # App#1 from this post    
    In [5]: %%timeit
         ...: sa = np.frombuffer(s,dtype='S1')
         ...: out = np.where(sa[:,None,None]=='0',[[1],[0]],[[0],[1]])
    100 loops, best of 3: 3.56 ms per loop
    
    # App#2 from this post    
    In [6]: %timeit ((np.frombuffer(s,dtype=np.uint8)[:,None]==[48,49])[...,None]).astype(float)
    1000 loops, best of 3: 1.81 ms per loop
    
    # App#3 from this post    
    In [7]: %%timeit
         ...: a = np.zeros([len(s), 2, 1])
         ...: idx = np.frombuffer(s,dtype=np.uint8)-48
         ...: a[np.arange(len(idx)),idx] = 1
    1000 loops, best of 3: 1.81 ms per loop
    

    【讨论】:

      【解决方案2】:

      一个简单的方法是从字符串创建一个list,然后通过指定dtype=int将此列表转换为整数的np.array

      s = '001010'
      
      a = np.array(list(s), dtype=int)
      # array([0, 0, 1, 0, 1, 0])
      

      然后使用np.where根据a中的值选择np.array([[1], [0]])np.array([[0], [1]])

      np.where(a==0, np.array([[1], [0]]), np.array([[0], [1]])).T[:,:,None]
      array([[[1],
              [0]],
      
             [[1],
              [0]],
      
             [[0],
              [1]],
      
             [[1],
              [0]],
      
             [[0],
              [1]],
      
             [[1],
              [0]]])
      

      【讨论】:

      • 其实 OP 想要一个数组数组,但仍然 +1 因为我认为,这就是他的真正意思
      • 在看到 OP 更新后,嗯不再。将不得不改变
      • 对不起,你能看看这个问题的更新版本吗?
      • 更新了答案@RomaKarageorgievich。让我知道这是否是你想要的。否则请分享预期输出
      • @RomaKarageorgievich 已更新以匹配预期输出
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 2019-12-28
      • 2019-11-24
      相关资源
      最近更新 更多