给定向量X和Y,计算数组C,使得C [i,j] = 1 /(x [i]-y [j])

时间:2019-08-01 16:33:34

标签: python arrays numpy

我试图通过循环来解决这个问题,但就我而言,性能也很重要。那么,有什么办法可以通过内置的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)

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

找到了该方法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)等。

答案 2 :(得分:-1)

  • 此解决方案在某些假设下有效。
  • 假设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)))