【问题标题】:Given vectors X and Y, compute array C such that C[i, j] = 1 / (x[i] - y[j])给定向量 X 和 Y,计算数组 C 使得 C[i, j] = 1 / (x[i] - y[j])
【发布时间】:2019-08-01 16:33:34
【问题描述】:

我试图用循环解决这个问题,但就我而言,性能也很重要。那么,有没有办法用 numpy 内置函数来解决这个问题呢?

这是我尝试过的代码:

import numpy as np

np.random.seed(123)
x = np.random.uniform(0, 1, 10)
y = np.random.uniform(0, 1, 20)

C = np.arange(100).reshape(10,20)

for i in range(10):
    for j in range(20):
        C[i, j] = 1 / (x[i] - y[j])

print(C)

【问题讨论】:

  • xy 总是有不同数量的元素吗?为什么C被定义为10乘10?
  • 是的!这就是问题 x 和 y 都不同。
  • 为什么C的首字母是(10,10),而y有20个元素?为什么不C = np.zeros((10,20))?然后循环jrange(20)。正如我的回答所示,像你一样初始化C 会在形状和dtype 方面产生问题。
  • 实际上,我使用了 10 和 20 都对我不起作用。
  • 为不同长度的两个向量之间的减法提供有效的数学定义。一旦你这样做了,问题就会得到解决。也许您想要一个 10 x 20 的向量,如上所述。你想做什么还不清楚。

标签: python arrays numpy


【解决方案1】:
In [158]: np.random.seed(123) 
     ...: x = np.random.uniform(0, 1, 10) 
     ...: y = np.random.uniform(0, 1, 20) 
     ...:  
     ...: C = np.arange(100).reshape(10,10) 
     ...:  
     ...: for i in range(10): 
     ...:     for j in range(10): 
     ...:         C[i, j] = 1 / (x[i] - y[j]) 
     ...: 

无循环版本是:

In [159]: np.allclose(1/(x[:,None]-y[None,:]),C)                                                             
...
ValueError: operands could not be broadcast together with shapes (10,20) (10,10) 

糟糕,计算有效,但生成了一个 (10,20) 数组,就像您通过仅循环 y 的一部分来创建 (10,10) 一样:

In [160]: np.allclose(1/(x[:,None]-y[None,:10]),C)                                                           
Out[160]: False

但是为什么它们不匹配呢?让我们检查一下这些值:

In [161]: C                                                                                                  
Out[161]: 
array([[   2,  -30,    3,    1,    3,  -24,    1,    1,    6,    6],
       [ -17,   -2,   -6,    4,   -8,   -2,    9,    9,   -4,   -4],
       [  -8,   -1,   -4,    5,   -5,   -1,   22,   19,   -3,   -3],
       [   4,   -5,    8,    2,    6,   -5,    2,    2,   50,   51],
       [   2, -104,    3,    1,    3,  -53,    1,    1,    5,    5],
       [  12,   -3,  -64,    2,   39,   -3,    4,    4,   -9,   -9],
       [   1,    3,    1,    1,    1,    4,    1,    1,    2,    2],
       [   2,  -22,    4,    1,    3,  -18,    1,    1,    6,    6],
       [   7,   -4,   23,    2,   12,   -3,    3,    3,  -19,  -19],
       [  20,   -2,  -21,    3, -168,   -2,    4,    4,   -7,   -7]])
In [162]: 1/(x[:,None]-y[None,:10])                                                                          
Out[162]: 
array([[   2.83052645,  -30.69318553,    3.87751788,    1.57037324,
           3.35092648,  -24.08117081,    1.94561063,    1.91932159,
           6.06362642,    6.07379914],
       [ -17.53196215,   -2.25779314,   -6.56026315,    4.41576282,
          -8.93615756,   -2.21309409,    9.64807633,    9.03443739,
          -4.07477972,   -4.07019868],
       [  -8.59648887,   -1.99124547,   -4.7232017 ,    5.98180728,
          -5.8413671 ,   -1.95639603,   22.54297209,   19.45536745,
          -3.2819175 ,   -3.2789451 ],
       [   4.80453349,   -5.62635579,    8.86976769,    2.03402156,
           6.52441214,   -5.35674196,    2.71132737,    2.66054378,
          50.5985934 ,   51.31578289],
       [   2.65751805, -104.37609732,    3.56002726,    1.5156313 ,
           3.11114844,  -53.97692265,    1.86227633,    1.83817713,
           5.32148144,    5.32931481],
       [  12.51119064,   -3.26858007,  -64.65886011,    2.75157239,
          39.90071936,   -3.17572279,    4.15602154,    4.0378801 ,
          -9.22127157,   -9.19784432],
       [   1.56841542,    3.97275499,    1.84436525,    1.0856746 ,
           1.71609023,    4.11914558,    1.25270511,    1.24175407,
           2.22611632,    2.22748596],
       [   2.92695729,  -22.61421767,    4.06079013,    1.59961138,
           3.48692684,  -18.80913104,    1.99069149,    1.96317869,
           6.52407795,    6.53585581],
       [   7.25932338,   -4.03034356,   23.60736785,    2.37386467,
          12.06452404,   -3.89008935,    3.35075535,    3.27353517,
         -19.75524346,  -19.64803083],
       [  20.4333914 ,   -2.96795626,  -21.5263349 ,    3.00806503,
        -168.72690268,   -2.89119379,    4.77040545,    4.61540389,
          -7.17185934,   -7.15768024]])

C 被初始化为整数 dtype,因此截断插入的任何浮点值。我们可以通过以下方式获得相同的效果:

In [163]: (1/(x[:,None]-y[None,:10])).astype(int)                                                            
Out[163]: 
array([[   2,  -30,    3,    1,    3,  -24,    1,    1,    6,    6],
       [ -17,   -2,   -6,    4,   -8,   -2,    9,    9,   -4,   -4],
       [  -8,   -1,   -4,    5,   -5,   -1,   22,   19,   -3,   -3],
       [   4,   -5,    8,    2,    6,   -5,    2,    2,   50,   51],
       [   2, -104,    3,    1,    3,  -53,    1,    1,    5,    5],
       [  12,   -3,  -64,    2,   39,   -3,    4,    4,   -9,   -9],
       [   1,    3,    1,    1,    1,    4,    1,    1,    2,    2],
       [   2,  -22,    4,    1,    3,  -18,    1,    1,    6,    6],
       [   7,   -4,   23,    2,   12,   -3,    3,    3,  -19,  -19],
       [  20,   -2,  -21,    3, -168,   -2,    4,    4,   -7,   -7]])

现在他们匹配了:

In [164]: np.allclose((1/(x[:,None]-y[None,:10])).astype(int),C)                                             
Out[164]: True

【讨论】:

    【解决方案2】:

    找到了这个方法fromfunction 应该做你想做的事。

    import numpy as np
    
    np.random.seed(123)
    x = np.random.uniform(0, 1, 10)
    y = np.random.uniform(0, 1, 20)
    
    # for a 10 by 20 array
    C = np.fromfunction(lambda i, j: 1/(x[i] - y[j]), (10, 20), dtype=int)
    
    # for a 10 by 10 array
    C = np.fromfunction(lambda i, j: 1/(x[i] - y[j]), (10, 10), dtype=int)
    
    # to avoid defining the shape
    C = np.fromfunction(lambda i, j: 1/(x[i] - y[j]), (x.size, y.size), dtype=int)
    

    如果您想将其设为所有整数,则只需执行 C.astype(int) 等操作即可。

    【讨论】:

      【解决方案3】:
      • 此解决方案在某些假设下有效。
      • 假设 x 和 y 只是一维向量。它们的大小可能不同。
      import numpy as np
      
      np.random.seed(123)
      x = np.random.uniform(0, 1, 10)
      y = np.random.uniform(0, 1, 20)
      
      # C = np.arange(100).reshape(10,10)
      ln = min(x.shape[0], y.shape[0])
      
      # this will get rid of manually defining C shape. Also works for any length of 1D x and y
      C = np.reciprocal(1/(x - y.reshape((-1,1))))
      
      # or you can also just simply do
      C = 1/(x - y.reshape((-1,1)))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-23
        • 2014-06-14
        • 2012-10-20
        • 2019-04-19
        • 1970-01-01
        • 1970-01-01
        • 2015-04-11
        相关资源
        最近更新 更多