我正在尝试将Pandas Dataframe(orders_df)中的两个现有列相乘 - 价格(股票收盘价)和金额(库存数量),并将计算添加到名为“Value”的新列中。由于某些原因,当我运行此代码时,“值”列下的所有行都是正数,而某些行应为负数。在DataFrame的Action列下,有七行包含'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)
请让我知道我做错了什么!
答案 0 :(得分:70)
我认为优雅的解决方案是使用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
此外,这应该是最快的解决方案。
答案 1 :(得分:27)
您可以使用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循环。
答案 2 :(得分:18)
如果我们愿意牺牲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
此解决方案需要两行代码而不是一行,但更容易阅读。我怀疑计算成本也是相似的。
答案 3 :(得分:5)
由于这个问题再次出现,我认为一个很好的干净方法是使用assign。
代码非常富有表现力和自我描述:
df = df.assign(Value = lambda x: x.Prices * x.Amount * x.Action.replace({'Buy' : 1, 'Sell' : -1}))
答案 4 :(得分:0)
对我来说,这是最清晰,最直观的:
<style scoped="true" lang="css">
.chat-box{
min-height: 270px;
width: 260px;
position: fixed;
right:0;
bottom: 0px;
color:#ffffff;
margin: 0px 10px 100px 0px;
background-color: #636b6f;
border-radius: 15px;
}
.title-area{
width:100%;
height: 35px;
border-top-left-radius:19px;
border-top-right-radius:19px;
text-align: center;
color:#ffffff;
font-size: 15px;
font-weight: bold;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.title{
float:left;
color:white;
margin: 5px 0px 0px 15px;
}
.close-icon{
font-weight: 900;
margin: 5px 15px 0px 0px;
float:right;
}
.chat-input-area{
bottom: 0px;
position: absolute;
height:40px;
padding: 10px;
margin-bottom: 10px;
}
.sendmessage-btn{
float:right
}
.textarea-input {
float: left;
width:74%
}
</style>
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
,允许您轻松地按元素倍增,然后您可以通过添加&#39;来累积生成列表。它。
答案 5 :(得分:0)
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))
答案 6 :(得分:0)
为了使事情更简洁,我采用了海顿的解决方案,但做了一个小功能。
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)
...并且任何修改仅需要在小函数本身中进行。
简洁,可读,整洁!