2系列的笛卡尔积

时间:2018-12-28 08:47:46

标签: python python-3.x numpy

我有一个很大的长度 t t = 200K行)

价格= [200,100,500,300 ..]

,我想计算一个矩阵( t X t ),其中值的计算方式为:

matrix[i][j] = prices[j]/prices[i] - 1

我尝试使用double进行此操作,但速度太慢。有什么想法可以更好地执行它吗?

for p0 in prices:
    for p1 in prices:
        matrix[i][j] = p1/p0 - 1

3 个答案:

答案 0 :(得分:2)

向量化解决方案使用np.meshgrid,并以prices1/prices作为参数(请注意,价格必须是数组),然后将结果相乘并减去1为了计算matrix[i][j] = prices[j]/prices[i] - 1

a, b = np.meshgrid(p, 1/p)
a * b - 1

例如:

p = np.array([1,4,2])

会给:

a, b = np.meshgrid(p, 1/p)
a * b - 1

array([[ 0.  ,  3.  ,  1.  ],
       [-0.75,  0.  , -0.5 ],
       [-0.5 ,  1.  ,  0.  ]])

快速检查一些单元格:

(i,j)    prices[j]/prices[i] - 1
--------------------------------
(1,1)        1/1 - 1 = 0
(1,2)        4/1 - 1 = 3
(1,3)        2/1 - 1 = 1
(2,1)        1/4 - 1 = -0.75

另一种解决方案:

[p] / np.array([p]).T - 1

array([[ 0.  ,  3.  ,  1.  ],
       [-0.75,  0.  , -0.5 ],
       [-0.5 ,  1.  ,  0.  ]])

答案 1 :(得分:1)

我想可以用这种方式完成

import numpy

prices = [200., 300., 100., 500., 600.]
x = numpy.array(prices).reshape(1, len(prices))
matrix = (1/x.T) * x - 1

让我详细解释。该矩阵是逐元素价格值的列向量和原始价格值的行向量的矩阵乘积。然后需要从结果中减去相同大小的矩阵。 首先,我们从价格清单创建行向量

x = numpy.array(prices).reshape(1, len(prices))

此处需要重塑。否则,向量将具有形状(len(prices),),而不是(1, len(prices))。 然后,我们计算元素价格倒数价格的列向量:

(1/x.T)

最后,我们计算出结果矩阵

matrix = (1/x.T) * x - 1

此处结尾的- 1将被广播到与(1/x.T) * x相同形状的矩阵中。

答案 2 :(得分:1)

有两种惯用的方式来执行外部产品类型的操作。可以使用通用函数的.outer方法,在此处np.divide

In [2]: p = np.array([10, 20, 30, 40])

In [3]: np.divide.outer(p, p)
Out[3]: 
array([[ 1.        ,  0.5       ,  0.33333333,  0.25      ],
       [ 2.        ,  1.        ,  0.66666667,  0.5       ],
       [ 3.        ,  1.5       ,  1.        ,  0.75      ],
       [ 4.        ,  2.        ,  1.33333333,  1.        ]])

或者,使用广播:

In [4]: p[:, None] / p[None, :]
Out[4]: 
array([[ 1.        ,  0.5       ,  0.33333333,  0.25      ],
       [ 2.        ,  1.        ,  0.66666667,  0.5       ],
       [ 3.        ,  1.5       ,  1.        ,  0.75      ],
       [ 4.        ,  2.        ,  1.33333333,  1.        ]])

p[None, :]本身可以拼写为重塑p.reshape((1, len(p))),但可读性强。

两者都等同于double for循环:

In [6]: o = np.empty((len(p), len(p)))

In [7]: for i in range(len(p)):
   ...:     for j in range(len(p)):
   ...:         o[i, j] = p[i] / p[j]
   ...:         

In [8]: o
Out[8]: 
array([[ 1.        ,  0.5       ,  0.33333333,  0.25      ],
       [ 2.        ,  1.        ,  0.66666667,  0.5       ],
       [ 3.        ,  1.5       ,  1.        ,  0.75      ],
       [ 4.        ,  2.        ,  1.33333333,  1.        ]])