将多行分配给一个名称

时间:2018-01-01 13:33:56

标签: r

在我的r代码中说:

a<-some code
b<-some code
c<-some code

我希望以某种方式保存这段代码,以便我可以随时调用它。如何将整个块保存为blockOfCode,以便我可以将其调用为宏?换句话说如下:

Z<-some code
a<-some code
b<-some code
c<-some code
Y<-some code
a<-some code
b<-some code
c<-some code
Z<-some code

可以改写为:

Z<-some code
blockOfCode
Y<-some code
blockOfCode
Z<-some code

3 个答案:

答案 0 :(得分:3)

您要求的是一个(与函数形成对比,后者接受参数并返回值而不是修改当前环境中的变量)。 R没有真正的宏。 This 2001 R News article by Thomas Lumley开始:

  

R邮件列表上熟悉的问题来源   是新转换的R用户正在尝试编写   然后R. Bill Venables的SAS或Stata代码指出   对他们来说,R不是一种宏观语言,而且是轻柔的   解释说,他们的解决方案更容易解决   问题。在本文中,我将解释一个宏   是的,为什么R不是一种宏观语言,这很好   如何将它合二为一。

Lumley提供的代码被放入gtools::defmacro()函数中,描述了更多here。这是一个例子:

library(gtools)
## defmacro() needs an argument, even if you don't use it
f <- defmacro(x,expr = {a <- a+1})
a <- 0
f()  ## you do need the parentheses here
a <- a+1

a的值现在为1.

expr可以包含任意数量的代码,因此您可以执行多个表达式。

但请阅读Lumley的文章。

答案 1 :(得分:0)

您的blockOfCode可以通过几种方式处理,但通常需要您了解环境。

如果您在全球环境中执行所有操作,则以下操作将起作用。

a <- b <- c <- NA

blockOfCode <- function() {
  a <<- 1
  b <<- 2
  c <<- 3
}

Z <- 11
blockOfCode()
Y <- 22
blockOfCode()
Z <- 33

如果本地环境(功能环境)中没有变量,深度分配箭头<<-将分配给全局环境。第一行a <- b <- c <- NA是必要的,因为如果您在没有首先创建变量c的情况下使用深度赋值,则会产生错误,可能是因为c()用于创建向量。通常我会尽量避免使用c作为变量。

此外,通常不鼓励深度分配,因为它可能会导致一些不可预测的结果。

您可以改为使用assign并指定环境。在这种情况下,使用parent.frame会将您从功能环境转移到全局环境。

blockOfCode <- function() {
  assign("a", 1, envir = parent.frame())
  assign("b", 2, envir = parent.frame())
  assign("c", 3, envir = parent.frame())
}

Z <- 11
blockOfCode()
Y <- 22
blockOfCode()
Z <- 33

这样做的好处是不需要提前创建a,b和c变量。您还可以指定另一个环境而不是全局环境。

所有这一切,你的例子可能太简单,无法说明你想要做什么。没有理由不止一次运行blockOfCode,因为a,b和c的值不会发生变化。在您更复杂的现实世界中,可能需要修改上述内容。

答案 2 :(得分:0)

以下是一些可能性:

1)eval / substitute 将代码块放在R函数中,但在编写函数时,将eval.parent(substitute({放在开头,将}))放在最后,然后只放在适当的点运行该功能。没有包使用。

block <- function() eval.parent(substitute({
  a <- 1
  b <- 2
  c <- 3
}))

Z <- 1
block()
cat("Z:", Z, "a:", a, "b:", b, "c:", c, "\n")
## Z: 1 a: 1 b: 2 c: 3 
rm(a, b, c)

Z <- 2
block()
cat("Z:", Z, "a:", a, "b:", b, "c:", c, "\n")
## Z: 2 a: 1 b: 2 c: 3 

2)附加通常最好避免将环境附加到搜索路径,因为它可能会导致一些意外行为,但它确实提供了另一种可能的解决方案。定义block2函数以返回environment(),然后附加运行函数的结果。请注意,这不会将abc放入全局环境中,而是将它们附加到位于搜索路径上的单独环境block2()中。可以使用ls("block2()")列出该环境的内容,并使用detach("block2()")删除该环境。没有包使用。

block2 <- function() {
  a <- 1
  b <- 2
  c <- 3
  environment()
}

Z <- 1
attach(block2())

search()   # note new 2nd element on search path
##  [1] ".GlobalEnv"        "block2()"          "package:stats"    
##  [4] "package:graphics"  "package:grDevices" "package:utils"    
##  [7] "package:datasets"  "package:methods"   "Autoloads"        
## [10] "package:base"  

ls("block2()")
## [1] "a" "b" "c"

cat("Z:", Z, "a:", a, "b:", b, "c:", c, "\n")
## Z: 1 a: 1 b: 2 c: 3 
detach("block2()")

Z <- 2
attach(block2())
cat("Z:", Z, "a:", a, "b:", b, "c:", c, "\n")
## Z: 2 a: 1 b: 2 c: 3 

3)quote / eval 将块的语句放入quote({...}),然后在运行时eval。没有包使用。

block3 <- quote({
  a <- 1
  b <- 2
  c <- 3
})

Z <- 1
eval(block3)
cat("Z:", Z, "a:", a, "b:", b, "c:", c, "\n")
## Z: 1 a: 1 b: 2 c: 3 
rm(a, b, c)

Z <- 2
eval(block3)
cat("Z:", Z, "a:", a, "b:", b, "c:", c, "\n")
## Z: 2 a: 1 b: 2 c: 3