首先,这个问题不是试图解决具体问题.作为R的新手,我也在努力创建更高效的代码和代码构建过程.获得关于不同编程方法甚至样式的观点是这个问题背后的原因.
以下是三种编码方式:
首先是示例数据:
stackexample <- c(52,50,45,49.5,50.5,12,10,14,11.5,12,110,108,106,101,104)
dim(stackexample)<- c(5,3)
Run Code Online (Sandbox Code Playgroud)
方法一:在函数中进行数学运算而不定义任何对象
ertimesIVCV1 <- function (x)
{ (solve(var(log((x[-nrow(x),])/(x[-1,])))))%*%
((1+(log(x[1,]/(x)[nrow(x),])))^(1/nrow(x))-1)}
ertimesIVCV1(stackexample)
Run Code Online (Sandbox Code Playgroud)
方法二:在函数中定义对象,然后操纵这些对象
ertimesIVCV2 <- function (x)
{ IVCV <- solve(var(log((x[-nrow(x),])/(x[-1,]))));
retsexcess <- (1+(log(x[1,]/(x)[nrow(x),])))^(1/nrow(x))-1;
IVCV%*%retsexcess}
ertimesIVCV2(stackexample)
Run Code Online (Sandbox Code Playgroud)
方法三:定义几个函数并在"类似摘要"函数中调用这些函数
IVCV <- function (x) {solve(var(log((x[-nrow(x),])/(x[-1,]))))}
retsexcess <- function(x) (1+(log(x[1,]/(x)[nrow(x),])))^(1/nrow(x))-1
ertimesIVCV3 <- function (x) {IVCV(x)%*%retsexcess(x)}
ertimesIVCV3(stackexample)
Run Code Online (Sandbox Code Playgroud)
所以都产生了相同的答案:
[,1]
[1,] 1.4430104
[2,] -0.1365155
[3,] 11.8088378
Run Code Online (Sandbox Code Playgroud)
但正如你可以看到三种不同的方法.
是否存在嵌入式函数的最佳数量,还是应该总是尝试明确列出所有数学?函数中有多少级别的函数是最佳的?这两种方法的计算速度都优越吗?对此有经验吗?你怎么看待这个?欢迎任何意见或建议或链接,谢谢!
黑麦
如果目标是时间效率,那么提供示例的答案是"谁在乎?".函数调用的开销不是决定效率的因素.您应该关注其他问题,例如用户理解和维护代码的能力.
require(rbenchmark)
benchmark(replications=100, ver1= ertimesIVCV1(stackexample),
ver2=ertimesIVCV2(stackexample),
ver3 = ertimesIVCV3(stackexample) )
# ------------------
test replications elapsed relative user.self sys.self user.child sys.child
1 ver1 100 0.030 1.000000 0.03 0 0 0
2 ver2 100 0.030 1.000000 0.03 0 0 0
3 ver3 100 0.031 1.033333 0.03 0 0 0
Run Code Online (Sandbox Code Playgroud)
恕我直言,速度效率应该是最后编写代码时,特别是如果你是一个初学者的你的关注.相反,您的主要关注点应该是简单性,可读性和模块性.不要误读我的意思,效率是一件好事,你会找到很多方法让你的代码在需要时更快,但它本身不应该是优先考虑的事情.
所以我将主要提供关于风格的提示.为了说明,这是我的代码版本的样子.请记住,我不知道你的代码在计算什么,所以我尽力使用有意义的变量名来破解它.
IVCV <- function(stack) {
## This function computes [...] IVCV stands for [...]
## Inputs:
## - stack: a matrix where each column [...]
## Output: a matrix [...]
n <- nrow(stack) # stack size
stack.ratios <- stack[-n, ] / stack[-1, ]
log.ratios <- log(stack.ratios)
ivcv <- solve(var(log.ratios))
return(ivcv)
}
ExcessReturn <- function(stack) {
## This function computes [...] IVCV stands for [...]
## Inputs:
## - stack: a matrix where each column [...]
## Output: a matrix [...]
n <- nrow(stack) # stack size
total.ratio <- stack[1, ] / stack[n, ]
excess.return <- (1 + log(total.ratio)) ^ (1 / n) - 1
return(excess.return)
}
ExcessReturnTimesIVCV <- function(stack) {
## This function computes [...] IVCV stands for [...]
## Inputs:
## - stack: a matrix where each column [...]
## Output: a vector [...]
return(IVCV(stack) %*% ExcessReturn(stack))
}
Run Code Online (Sandbox Code Playgroud)
1)是的,将代码分解为小函数.它的可读性,灵活性和维护性更好.它还使单元测试更容易,您可以在其中为每个基本代码设计测试.
2)通过在函数体内包含关于其描述/输入/输出的注释来记录函数.这样,在创建函数之后,用户可以将其描述视为函数打印输出的一部分(例如,只需键入ExcessReturnTimesIVCVGUI).
3)将复杂性分解为多个语句.现在,你的三条建议都难以理解,每条线上都有太多的东西.声明应该做一个简单的事情,以便它可以轻松阅读.创建更多对象不太可能减慢您的过程,并且它将使调试更容易.
4)您的对象名称是使您的代码清晰的关键.选择它们并使用一致的语法.我使用UpperCamelCase作为我自己的函数名称,而小写单词则用点分隔,用于大多数其他对象.
5)发表评论,尤其是3)和4)不足以使代码清晰.在我的例子中,我选择使用变量n.我反对变量名称应该是描述性的建议,但它是为了使代码更轻stack[-n, ] / stack[-1, ]一些,并给出一些非常对称的表达式.由于n名字不好,我发表评论解释其含义.如果我知道函数真正在做什么,我可能还会在代码中添加更多注释.
6)使用一致的语法规则,主要是为了提高可读性.你会听到关于这里应该使用什么的不同意见.一般来说,没有一种最好的方法.最重要的是做出选择并坚持下去.所以这是我的建议:
a)每行一个陈述,没有半冒号.
b)一致的间距和压痕(无标签).我把逗号后面的空格放在二元运算符周围.如果它有助于提高可读性,我还会使用额外的间距排列.
c)一致的支撑:注意使用大括号来定义块的方式,否则你可能会在脚本模式下遇到问题.参见R Inferno的 8.1.43节(一个很好的参考).
祝好运!