Подтвердить что ты не робот

Я хочу умножить два столбца в pandas DataFrame и добавить результат в новый столбец

Я пытаюсь умножить два существующих столбца в pandas Dataframe (orders_df) - Цены (цена закрытия акций) и Сумма (количество запасов) и добавить вычисление в новый столбец под названием "Значение". По какой-то причине, когда я запускаю этот код, все строки в столбце "Значение" представляют собой положительные числа, а некоторые из строк должны быть отрицательными. В столбце "Действие" в DataFrame есть семь строк с строкой "Sell" и семь с строкой "Купить".

for i in orders_df.Action:
 if i  == 'Sell':
  orders_df['Value'] = orders_df.Prices*orders_df.Amount
 elif i == 'Buy':
  orders_df['Value'] = -orders_df.Prices*orders_df.Amount)

Пожалуйста, дайте мне знать, что я делаю неправильно!

4b9b3361

Ответ 1

Если мы готовы пожертвовать кратким решением Хейдена, можно также сделать что-то вроде этого:

In [22]: orders_df['C'] = orders_df.Action.apply(
               lambda x: (1 if x == 'Sell' else -1))

In [23]: orders_df   # New column C represents the sign of the transaction
Out[23]:
   Prices  Amount Action  C
0       3      57   Sell  1
1      89      42   Sell  1
2      45      70    Buy -1
3       6      43   Sell  1
4      60      47   Sell  1
5      19      16    Buy -1
6      56      89   Sell  1
7       3      28    Buy -1
8      56      69   Sell  1
9      90      49    Buy -1

Теперь мы устранили необходимость в выражении if. Используя DataFrame.apply(), мы также устраняем цикл for. Как отметил Хейден, векторизованные операции всегда бывают быстрее.

In [24]: orders_df['Value'] = orders_df.Prices * orders_df.Amount * orders_df.C

In [25]: orders_df   # The resulting dataframe
Out[25]:
   Prices  Amount Action  C  Value
0       3      57   Sell  1    171
1      89      42   Sell  1   3738
2      45      70    Buy -1  -3150
3       6      43   Sell  1    258
4      60      47   Sell  1   2820
5      19      16    Buy -1   -304
6      56      89   Sell  1   4984
7       3      28    Buy -1    -84
8      56      69   Sell  1   3864
9      90      49    Buy -1  -4410

Это решение принимает две строки кода вместо одного, но немного легче читать. Я подозреваю, что вычислительные затраты тоже схожи.

Ответ 2

Я думаю, что элегантным решением является использование метода where (также см. API docs):

In [37]: values = df.Prices * df.Amount

In [38]: df['Values'] = values.where(df.Action == 'Sell', other=-values)

In [39]: df
Out[39]: 
   Prices  Amount Action  Values
0       3      57   Sell     171
1      89      42   Sell    3738
2      45      70    Buy   -3150
3       6      43   Sell     258
4      60      47   Sell    2820
5      19      16    Buy    -304
6      56      89   Sell    4984
7       3      28    Buy     -84
8      56      69   Sell    3864
9      90      49    Buy   -4410

Далее это должно быть самым быстрым решением.

Ответ 3

Вы можете использовать метод DataFrame apply:

order_df['Value'] = order_df.apply(lambda row: (row['Prices']*row['Amount']
                                               if row['Action']=='Sell'
                                               else -row['Prices']*row['Amount']),
                                   axis=1)

Как правило, быстрее использовать эти методы, а не более для циклов.

Ответ 4

Поскольку этот вопрос снова возник, я думаю, что хороший чистый подход использует assign.

Код довольно выразительный и самоописательный:

df = df.assign(Value = lambda x: x.Prices * x.Amount * x.Action.replace({'Buy' : 1, 'Sell' : -1}))

Ответ 5

Для меня это самый ясный и самый интуитивный:

values = []
for action in ['Sell','Buy']:
    amounts = orders_df['Amounts'][orders_df['Action'==action]].values
    if action == 'Sell':
        prices = orders_df['Prices'][orders_df['Action'==action]].values
    else:
        prices = -1*orders_df['Prices'][orders_df['Action'==action]].values
    values += list(amounts*prices)  
orders_df['Values'] = values

Метод .values возвращает numpy array, позволяющий легко размножать элементы, а затем вы можете скомпилировать список, добавив его к нему.