[英]How to multiply two columns of a pandas data-frame (row multiplication) and store the result in a new column?
[英]I want to multiply two columns in a pandas DataFrame and add the result into a new column
我正在嘗試將 pandas Dataframe ( orders_df
) 中的兩個現有列相乘: Prices
(股票收盤價)和Amount
(庫存數量),並將計算添加到名為Value
的新列中。 出於某種原因,當我運行這段代碼時,“ Value
”列下的所有行都是正數,而某些行應該是負數。 在 DataFrame 的“操作”列下,有七行帶有'Sell'
字符串,七行帶有'Buy'
字符串。
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)
請讓我知道我做錯了什么!
我認為一個優雅的解決方案是使用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
此外,這應該是最快的解決方案。
您可以使用 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)
使用這些方法通常比 for 循環更快。
如果我們願意犧牲 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
循環。 正如海登所指出的,矢量化操作總是更快。
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
這個解決方案需要兩行代碼而不是一行代碼,但更容易閱讀。 我懷疑計算成本也相似。
由於這個問題再次出現,我認為一個很好的清潔方法是使用assign 。
該代碼非常具有表現力和自我描述性:
df = df.assign(Value = lambda x: x.Prices * x.Amount * x.Action.replace({'Buy' : 1, 'Sell' : -1}))
為了使事情變得整潔,我采用了海登的解決方案,但從中做了一個小功能。
def create_value(row):
if row['Action'] == 'Sell':
return row['Prices'] * row['Amount']
else:
return -row['Prices']*row['Amount']
這樣當我們想將函數應用到我們的數據幀時,我們可以做..
df['Value'] = df.apply(lambda row: create_value(row), axis=1)
...並且任何修改只需要發生在小函數本身中。
簡潔、易讀、整潔!
對我來說,這是最清晰、最直觀的:
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
允許您輕松地按元素相乘,然后您可以通過“添加”累積生成一個列表。
來自 bmu 的好解決方案。 我認為將值放在括號內而不是放在括號外更具可讀性。
df['Values'] = np.where(df.Action == 'Sell',
df.Prices*df.Amount,
-df.Prices*df.Amount)
使用一些內置函數的熊貓。
df['Values'] = np.where(df.Action.eq('Sell'),
df.Prices.mul(df.Amount),
-df.Prices.mul(df.Amount))
首先,將Prices
和Amount
列相乘。 如果條件為True ,則隨后使用mask
取反值:
df.assign(
Values=(df["Prices"] * df["Amount"]).mask(df["Action"] == "Buy", lambda x: -x)
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.