答案 0 :(得分:8)
你的代码看起来很奇怪,似乎你对R来自另一种编程语言有很多误解。 Gavin和Gillespie已经指出了为什么你得到了warniong。让我为更优化的编码添加一些技巧:
[ - 1]并不意味着:放弃最后一个。这意味着“保留除了第一个值之外的所有内容”,这也解释了为什么会出现错误结果。
在开始时计算常见事物,以整理代码。
head(x$TradeResult.Currency., n = 1)
与x$TradeResult.Currency.[1]
相同。
密切关注你的向量。代码中的大多数错误都来自忘记你正在使用向量。
如果您需要一个值作为向量中的第一个,请将您使用的任何循环的OUTSIDE置于其中,切勿在函数中添加if子句。
预先定义您的矢量/矩阵,在处理大数据时速度更快,内存更少。
矢量化,矢量化,矢量化。我是否提到矢量化?
了解如何使用debug()
,debugonce()
和browser()
来检查您的功能正在做什么。您可以通过在函数内操作时检查对象来解决许多问题。
这说并考虑到了,你的功能变为:
CalculateIndex <- function(x,accountValueStart){
# predifine your vector
indexedValues <- vector("numeric",nrow(x))
# get your totalAccount calculated FAST. This is a VECTOR!!!
totalAccount <- cumsum(c(accountValueStart,x$TradeResult.Currency.))
#adjust length:
totalAccount <- totalAccount[-(nrow(x)+1)]
# only once this calculation. This is a VECTOR!!!!
totRatio <- 1+(((x$Size.Units. * x$EntryPrice)/totalAccount) *
x$TradeResult.Percent.)/100
# and now the calculations
indexedValues[1] <- 100 * totRatio[1]
for(i in 2:nrow(x)){
indexedValues[i] <- indexedValues[i-1]*totRatio[i]
}
return(indexedValues)
}
并返回
> CalculateIndex(theData,14000)
[1] 99.97901 99.92081 99.57714 101.46399 102.35708 101.28586 103.31497
103.80656 102.33612 104.35856 102.79509 103.56012
[13] 102.90879 103.67281 104.85296 104.60432 102.50553 102.90490 102.71800
104.06766
现在你做了:
invisible(replicate(10,print("I will never forget about vectorization any more!")))
答案 1 :(得分:4)
警告信息来自这一行:
if(x$TradeResult.Currency == head(x$TradeResult.Currency., n = 1)){
很容易理解为什么; x$TradeResult.Currency
是向量,因此与head(x$TradeResult.Currency., n = 1)
的比较会产生逻辑的向量。 (顺便说一句,为什么不x$TradeResult.Currency[1]
而不是head()
来电?)。 if()
需要单个逻辑而不是逻辑向量,这就是警告的内容。如果你想根据给出逻辑向量的条件做两件事之一,ifelse()
很有用。
实际上,你所做的只是输入语句的if()
部分而且只执行一次,因为x$TradeResult.Currency == head(x$TradeResult.Currency., n = 1)
的第一个元素是TRUE
而R忽略了其他
> if(c(TRUE, FALSE)) {
+ print("Hi")
+ } else {
+ print("Bye")
+ }
[1] "Hi"
Warning message:
In if (c(TRUE, FALSE)) { :
the condition has length > 1 and only the first element will be used
> ifelse(c(TRUE, FALSE), print("Hi"), print("Bye"))
[1] "Hi"
[1] "Bye"
[1] "Hi" "Bye"
至于解决你的真实问题:
CalculateIndex2 <- function(x, value, start = 100) {
rowSeq <- seq_len(NROW(x))
totalAc <- cumsum(c(value, x$TradeResult.Currency.))[rowSeq]
idx <- numeric(length = nrow(x))
interm <- (((x$Size.Units. * x$EntryPrice) / totalAc) *
x$TradeResult.Percent.) / 100
for(i in rowSeq) {
idx[i] <- start + (start * interm[i])
start <- idx[i]
}
idx
}
在theData
上使用时给出:
> CalculateIndex2(theData, 14000)
[1] 99.97901 99.92081 99.57714 101.46399 102.35708 101.28586 103.31497
[8] 103.80656 102.33612 104.35856 102.79509 103.56012 102.90879 103.67281
[15] 104.85296 104.60432 102.50553 102.90490 102.71800 104.06766
你想要的是一个递归函数(IIRC);当前索引是前一个索引的一些功能。这些很难用R中的矢量化方式解决,因此就是循环。
答案 2 :(得分:2)
我仍然对你究竟想做什么感到困惑,但希望以下内容会有所帮助。
您的R脚本为第一个值提供与Excel函数相同的答案。你看到了一个区别,因为R没有打印出所有数字。
> tmp = CalculateIndex(thedata)
Warning message:
In if (x$TradeResult.Currency == head(x$TradeResult.Currency., n = 1)) { :
the condition has length > 1 and only the first element will be used
> print(tmp, digits=10)
[1] 99.97900857 99.94180357 99.65632286 101.88688500 100.89308643
<snip>
警告消息的原因是因为x$TradeResult.Currency
是与单个数字进行比较的向量。
该警告信息也是您的错误所在。在if
语句中,从不执行else部分,因为只使用x$TradeResult.Currency
的值。如警告消息所述,仅使用x$TradeResult.Currency
的第一个元素。