Chcę pomnożyć dwie kolumny w ramce danych i dodać wynik do nowej kolumny

Próbuję pomnożyć dwie istniejące kolumny w ramce danych pandy (orders_df) - ceny (cena zamknięcia zapasów) i ilość (ilości zapasów) i dodać obliczenia do nowej kolumny o nazwie "wartość". Z jakiegoś powodu, gdy uruchamiam ten kod, wszystkie wiersze w kolumnie "Wartość" są liczbami dodatnimi, podczas gdy niektóre wiersze powinny być ujemne. Pod Kolumną działania w ramce danych znajduje się siedem wierszy z ciągiem "Sprzedaj" i siedem z ciągiem "kupuj".

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)

Proszę dać mi znać co robię źle !

Author: bmu, 2012-12-27

5 answers

Jeśli jesteśmy gotowi poświęcić zwięzłość rozwiązania Haydena, można również zrobić coś takiego:]}

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

Teraz wyeliminowaliśmy potrzebę if stwierdzenia. Używając DataFrame.apply(), usuwamy również pętlę for. Jak zauważył Hayden, operacje wektorowe są zawsze szybsze.

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

To rozwiązanie zajmuje dwie linie kodu zamiast jednej, ale jest nieco łatwiejsze do odczytania. Podejrzewam, że koszty obliczeniowe również są podobne.

 14
Author: Aman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-27 20:05:45

Myślę, że eleganckim rozwiązaniem jest użycie where metoda (Zobacz też 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
To powinno być najszybsze rozwiązanie.
 61
Author: bmu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-14 05:47:30

Możesz użyć ramki danych apply "metoda": {]}

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

zwykle jest to szybsze stosowanie tych metod, a nie over for loops.

 21
Author: Andy Hayden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-27 18:59:12

Ponieważ to pytanie pojawiło się ponownie, myślę, że dobrym czystym podejściem jest użycie assign .

Kod jest dość wyrazisty i samoopisujący:

df = df.assign(Value = lambda x: x.Prices * x.Amount * x.Action.replace({'Buy' : 1, 'Sell' : -1}))
 4
Author: FLab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-25 14:18:35

Dla mnie jest to najczystsze i najbardziej intuicyjne:

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

Metoda .values zwraca numpy array pozwalając na łatwe mnożenie elementów, a następnie można skumulowane generowanie listy przez "dodanie" do niej.

 0
Author: Michael Silverstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-25 14:06:12