75

I'm trying to multiply two existing columns in a pandas Dataframe (orders_df) - Prices (stock close price) and Amount (stock quantities) and add the calculation to a new column called 'Value'. For some reason when I run this code, all the rows under the 'Value' column are positive numbers, while some of the rows should be negative. Under the Action column in the DataFrame there are seven rows with the 'Sell' string and seven with the 'Buy' string.

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)

Please let me know what i'm doing wrong !

4

7 に答える 7

87

エレガントな解決策は、この方法を使用することだと思います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

さらに、これが最速のソリューションになるはずです。

于 2012-12-28T14:47:45.373 に答える
34

DataFrameapplyメソッドを使用できます。

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

通常、for ループを使用するよりも、これらのメソッドを使用する方が高速です。

于 2012-12-27T18:59:12.093 に答える
25

Hayden のソリューションの簡潔さを犠牲にしても構わないと思っている場合は、次のようなこともできます。

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ループも廃止します。Hayden が指摘したように、ベクトル化された操作は常に高速です。

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

このソリューションは 1 行ではなく 2 行のコードを必要としますが、読みやすくなっています。計算コストも似ていると思います。

于 2012-12-27T20:05:45.073 に答える