Умножить вектор на датафрейме - векторизовать - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть пандас с размером данных 2441x1441 (A), который равен нулю в верхнем треугольнике - диагноз имеет значения.Я хотел бы умножить каждый столбец этого вектора с длиной 2441 (B).Сложность в том, что я хочу, чтобы первое ненулевое значение A умножалось на первое значение B (и второе значение A на второе значение B и т. Д.).Это должно произойти для всех столбцов A и привести к другому кадру данных, C.

A=pd.DataFrame(
[[1, 0, 0],
[3, 4, 0],
[6, 7, 8]])

B=np.array([1,2,3,4]).T

Здесь результат будет

C=[ 1,  0, 0,
    6,  4, 0,
   18, 14, 8]

Я сделал цикл for, где я могу перебиратьчерез каждое значение

for x in range(0,len(B)):
    C = (A.iloc[192+x:,:].T*B[0:len(B)-x]).T

Однако это очень медленно, и мне нужно многократно повторять эту операцию для разных наборов данных.Есть ли хороший и питонный способ векторизации этого?

Ответы [ 3 ]

0 голосов
/ 26 ноября 2018

Вот способ сделать это:

Вы можете создать нижнюю треугольную матрицу из B, обрезав и добавив к нулю вектор B по каждому столбцу, чтобы все его верхние треугольные части были нулями,

Таким образом, по сути, вы реплицируете операцию умножения матриц.Затем вам просто нужно умножить поэлементно две матрицы, используя A*new_B или np.multiply(A,new_B).

new_b = np.array([list(np.pad(B[:-i] if i != 0 else B,(i,0), 'constant')) 
                  for i in range(len(B))]).T[:len(A),:len(A)]

print(new_b)
array([[1, 0, 0],
       [2, 1, 0],
       [3, 2, 1]])

print(new_b*A)
array([[ 1,  0,  0],
       [ 6,  4,  0],
       [18, 14,  8]])
0 голосов
/ 26 ноября 2018

Используйте np.fromfunction, чтобы определить матрицу, чьи записи - это нужные вам множители.Например, если

A = np.array([[1, 0, 0],
              [3, 4, 0],
              [6, 7, 8]])

, то

B = np.clip(np.fromfunction(lambda i, j: i-j+1, A.shape), 0, None)

даст вам

B = np.array([[1, 0, 0],
              [2, 1, 0],
              [3, 2, 1]])

, а затем требуемый результат будет просто поэлементным произведением Aи B:

C = A * B

приводит к

C = np.array([[1,  0,  0],
              [6,  4,  0],
              [18, 14, 8]])

Фактически, поскольку ваш A имеет нижнюю треугольную форму, вы можете отбросить вызов до np.clip в определенииB и получите тот же C.

Редактировать: Я немного неверно истолковал вопрос.Если B в OP (позвольте мне назвать это b, поскольку я уже использовал B) не является последовательностью натуральных чисел, вы можете сделать

 B = np.tril(
         np.fromfunction(
             lambda i, j: b[np.clip((i-j).astype(int), 0, b.shape[0])],
             A.shape))

Например,если

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

, то вы получите

 B = np.array([[2, 0, 0],
               [3, 2, 0],
               [1, 3, 2]])
0 голосов
/ 26 ноября 2018

ОК, а как насчет создания массива из вашего вектора B, который соответствует фигуре, которую вы ищете?После того, как вы преобразовали его таким образом, вы можете выполнить поэлементное умножение, и все правильные значения будут выровнены., но поскольку у вашего вектора A уже есть нули в этих позициях, не имеет значения, какие значения будут в этих позициях умножающего массива - поэтому шаг np.tril не является действительно необходимым.

В любом случае, независимо от ваших предпочтений, как только вы получите эту форму (и, возможно, существует лучший способ, чем тот, который использовался выше для получения этой формы), тогда вы можете np.multiply два объекта, которые будутнесколько выровненных элементов.

np.multiply(A, np.tril(mB.T))

>>>> array([[ 1,  0,  0],
            [ 6,  4,  0],
            [18, 14,  8]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...