Условное поэлементное умножение двух кадров данных pandas

Я изо всех сил пытаюсь выполнить базовое условное поэлементное умножение между двумя кадрами данных. Предположим, у меня есть следующие два фрейма данных:

df1 = pd.DataFrame({'A': [-0.1,0.3,-0.4, 0.8,-0.5,-0.1,0.3,-0.4, 0.8,-1.2],'B': [-0.2,0.5,0.3,-0.5,0.1,-0.2,0.5,0.3,-0.5,0.9]},index=[0, 1, 2, 3,4,5,6,7,8,9])
df2=pd.DataFrame({'C': [-0.003,0.03848,-0.04404, 0.018,-0.1515,-0.02181,0.233,-0.0044, 0.01458,-0.015],'D': [-0.0152,0.0155,0.03,-0.0155,0.0151,-0.012,0.035,0.0013,-0.0005,0.009]},index=[0, 1, 2, 3,4,5,6,7,8,9])

Идея состоит в том, чтобы умножить df1 and df2.shift(-1) (поэлементно, а не умножение матриц) в зависимости от значений df1. Если (df1>=0.50 or df1<=-0.50), то я умножаю df1 и df2.shift(-1). В противном случае я просто ставлю 0.

Желаемый результат в этом примере должен быть следующим (с именами столбцов, являющимися именами столбцов df1, а также индексом df1):

df3=pd.DataFrame({'A': [0,0,0, -0.1212,0.010905,0,0,0, -0.012,'NaN'],'B': [0,0.015,0,-0.00755,0,0,0.00065,0,-0.0045,'NaN']},index=[0, 1, 2, 3,4,5,6,7,8,9])

Я попробовал следующий код:

import numpy as np
import pandas as pd
df3=np.where((df1>=0.50 or df1 <=-0.50),df1*df2.shift(-1),0)

И я получаю, что истинное значение DataFrame неоднозначно. Используйте a.empty, a.bool(), a.item(), a.any() или a.all(). Спасибо.


person CTXR    schedule 23.11.2018    source источник


Ответы (1)


Используйте | для побитового OR с конструктором DataFrame:

arr = np.where((df1>=0.50) | (df1 <=-0.50),df1*df2.shift(-1),0)
df3 = pd.DataFrame(arr, index=df1.index, columns=df1.columns)
print (df3)
          A        B
0  0.000000  0.00000
1  0.000000  0.01500
2  0.000000  0.00000
3 -0.121200 -0.00755
4  0.010905  0.00000
5  0.000000  0.00000
6  0.000000  0.00065
7  0.000000  0.00000
8 -0.012000 -0.00450
9       NaN      NaN

Решение Numpy должно быть быстрее:

arr2 = np.concatenate([df2.values[1:, ], 
                       np.repeat(np.nan, len(df2.columns))[None, :]])

arr = np.where((df1.values>=0.50) | (df1.values <=-0.50),df1.values*arr2,0)
df3 = pd.DataFrame(arr, index=df1.index, columns=df1.columns)
print (df3)
          A        B
0  0.000000  0.00000
1  0.000000  0.01500
2  0.000000  0.00000
3 -0.121200 -0.00755
4  0.010905  0.00000
5  0.000000  0.00000
6  0.000000  0.00065
7  0.000000  0.00000
8 -0.012000 -0.00450
9       NaN      NaN
person jezrael    schedule 23.11.2018
comment
Работает, спасибо за объяснение. Последнее: я попробовал это на реальных кадрах данных и получил ошибку: операнды не могут быть переданы вместе с формами (3951,1056) (7902,2112). Я проверил размер двух кадров данных перед выполнением вычислений, и они оба (3951,1056). Не уверен, почему он удвоил размер второго фрейма данных. Спасибо - person CTXR; 23.11.2018
comment
Возможно, проблема с разными именами индексов или столбцов, попробуйте изменить df1*df2.shift(-1) на df1.values*df2.shift(-1).values - person jezrael; 23.11.2018
comment
Сейчас работает с этим. Также попробовал ваше второе решение с numpy, тоже работает. Благодарю вас! - person CTXR; 23.11.2018
comment
Первое решение не работает. ValueError: operands could not be broadcast together with shapes (10,2) (10,4) () - person ; 23.11.2018
comment
Да. Это обсуждалось в комментариях, работает, если добавить .values - person CTXR; 23.11.2018