Декартово произведение из 2 серий - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть большая серия длиной т ( т = 200 тыс. Строк)

цены = [200, 100, 500, 300 ..]

и я хочу вычислить матрицу ( t X t ), где значение вычисляется как:

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

Я пробовал это с использованием двойнойдля, но это слишком медленно.Есть идеи, как это сделать лучше?

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

Ответы [ 3 ]

0 голосов
/ 28 декабря 2018

Полагаю, это можно сделать таким образом

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.

0 голосов
/ 28 декабря 2018

Существует два идиоматических способа выполнения внешней операции типа продукта.Либо используйте метод универсальных функций .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))), но удобочитаемость.

Оба эквивалентны двойному циклу 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.        ]])
0 голосов
/ 28 декабря 2018

Векторизованное решение использует np.meshgrid, с prices и 1/prices в качестве аргументов (обратите внимание, что цены должны быть массивом) и умножает результат и вычитает 1, чтобыcompute 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.  ]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...