我刚刚开始学习R(实际上,只有一天的经验),我正在尝试将SQL代码迁移到R只是为了看看它们的比较。
其中一个用例是计算平均股票购买价格。现在在我的数据中,我有负数和正数的交易,只有+体积用于计算平均值。另一方面,具有 - 交易量的行需要平均购买价格,因为之后用于计算该销售交易的盈利/亏损。
可以像这样构建样本数据:
df = data.frame(matrix(rnorm(20)*10, nrow=10))
df$X3 <- df$X2 * df$X2
然后我有一个函数来计算avg:
avgPurchasePrice <- function(volume, eurPrice){
price <- vector(mode="numeric", length=length(volume))
s=0
t=0
for(i in 1:length(volume)){
if(volume[i]>0){
price[i] <- volume[i]*eurPrice[i]+t;
volume[i]<-volume[i]+s;
s <- volume[i];
t <- price[i];
} else {
volume[i] <- s;
price[i] <-t;
}
volume[i]=price[i]/volume[i];
}
volume
}
和平均值计算为
df$avgPrice <- avgPurchasePrice(df$X1,df$X3)
问题:这种方法可以吗?我不知道R并且可能有更好的方法/模式来实现它,因为这种方法似乎非常“传统”
编辑:
我认为应该是:对于每个正数量,计算平均(买入)价格作为总价格与总交易量的比率;负数量使用最后一个值而不改变它
我查看了dplyr并想出了这个(只适用于我的数据文件)
stock %>% group_by(FINANCIAL_INSTRUMENT) %>% mutate( cumPrice=cumsum(vol=ifelse(VOLUME>0,VOLUME,0L)*PricE), cumVol=cumsum(ifelse(VOLUME>0L,VOLUME,0L)),
cumPrice/cumVol)
答案 0 :(得分:1)
这是原始代码,几乎没有改进,并且dplyr与原生R代码的等效解决方案
set.seed(323)
df = data.frame(matrix(rnorm(20)*10, nrow=10))
df[,2]=abs(df[,2])
colnames(df)<-c("Volume","Price")
#df$EurPrice <- df$Volume * df$Price
avgPurchasePrice <- function(volume, eurPrice){
price <- vector(mode="numeric", length=length(volume))
s=0
t=0
avpr=vector()
for(i in 1:length(volume)){
if(volume[i]>0){
price[i] <- volume[i]*eurPrice[i]+t;
volume[i]<-volume[i]+s;
s <- volume[i];
t <- price[i];
} else {
volume[i] <- s;
price[i] <-t;
}
avpr[i]=price[i]/volume[i];
}
avpr
}
#average
df$avgPrice <- avgPurchasePrice(df$Volume,df$Price)
df$avgPrice2<-cumsum(ifelse(df$Volume>0,df$Volume,0)*df$Price)/cumsum(ifelse(df$Volume>0,df$Volume,0))
df
Volume Price avgPrice avgPrice2 1 -5.332687 2.0293922 NaN NaN 2 12.148825 3.8633988 3.863399 3.863399 3 7.528894 1.3639138 2.907071 2.907071 4 2.158501 6.1042484 3.223110 3.223110 5 8.886568 13.2210598 6.115018 6.115018 6 7.884685 13.7922340 7.682912 7.682912 7 1.436665 8.9700328 7.729090 7.729090 8 -2.235569 2.0624435 7.729090 7.729090 9 8.707973 0.2852434 6.399490 6.399490 10 3.924928 1.0760426 6.002844 6.002844