如何在R中使用变量给另一个变量命名?

8
我有一个使用readline的函数,允许用户输入他们想要为我创建的变量的名称。我们称之为“USER.DEFINED.VARIABLE”。它包含了我想要用于另一个变量的名称。假设"USER.DEFINED.VARIABLE"被设置为"jimsfilename"。
我知道可以使用以下语句为名为"jimsfilename"的变量赋值:
assign(USER.DEFINED.VARIABLE,c(1,2,3,4,5))

"jimsfilename"现在会有1,2,3,4,5。但是,由于在readline将其分配给USER.DEFINED.VARIABLE之前我不知道它的名称,那么我现在该如何调整“jimsfilename”呢?

换句话说,假设我现在想要将jimsfilename中的每个值都加1,我不能这样做:

USER.DEFINED.VARIABLE <- USER.DEFINED.VARIABLE + 1 # can't do this

因为"USER.DEFINED.VARIABLE"实际上是一个文本字符串名称。我想引用jimsfilename,但我只有USER.DEFINED.VARIABLE来表示它。我相信这很容易解决...

3个回答

10

这取决于您想要做什么,但以下是使用get函数的示例:

x = 1
get("x") + 1

2

assign("name", get("x") + 1)
name

2


3
为什么不将变量的所有操作(如添加 1 或其他更改)都放到一个本地变量中,然后在函数/脚本/其它结尾处进行赋值或保存呢?这比创建变量并使用 "get" 获取副本、更改它,然后再 "assign" 它要简单得多。
更好的做法是在函数内部使用自己的变量名,然后只返回结果,让用户在那时决定如何命名。这是更加专业的做法,最好根本不使用 "assign" 函数。大多数可以用 "assign" 完成的任务都可以通过使用列表和下标来更简单地完成。
函数不应该改变全局环境中的任何东西,只需返回用户可能需要的任何值,并让用户进行赋值。

+1 - 是的,请使用列表。不要使用“assign”,而是使用“aList[[USER.DEFINED.VARIABLE]] <- c(1,2,3,4,5)”,并且不要使用“get”,而是使用“aList[[USER.DEFINED.VARIABLE]] <- aList[[USER.DEFINED.VARIABLE]] + 1”。 - flodel

1
你可以使用evalparse。后者将文本解释为控制台中的输入。第一个评估表达式(例如由parse生成的)。示例:
> varname <- "user.defined.variable"
> varvalue <- 42
> eval(parse(text=paste(varname, varvalue, sep=" <- ")), envir=.GlobalEnv)
> ls()
[1] "user.defined.variable" "varname"               "varvalue"             
> user.defined.variable
[1] 42

请注意,我已选择全局环境作为新变量的目标。如果不是这种情况,您可以进行适当的更改。
要稍后引用新变量,可以使用as.symbol。只需在分配新变量的环境下评估它即可:
> eval(as.symbol(varname), envir=.GlobalEnv)
[1] 42

你也可以使用substitute创建eval能够理解的表达式:
> eval(substitute(x+1, list(x=as.symbol(varname))), envir=.GlobalEnv)
[1] 43

要更改新变量,只需创建赋值表达式并进行评估:
> eval(substitute(x <- x*10, list(x=as.symbol(varname))), envir=.GlobalEnv)
> eval(as.symbol(varname), envir=.GlobalEnv)
[1] 420

1
我认为你正在向一个不需要的新用户暴露语言复杂性,这些复杂性可以更容易地通过“get”来解决。 - IRTFM
非常同意@DWin的观点。虽然我知道这是出于善意,但我很想给这个答案投反对票,因为我认为这是非常糟糕的建议。 - Ben Bolker
@BenBolker,@DWin。各位,让我们不要低估我们的新用户... 当我完全是R的新手时,我对所有那些deparsesubstitutes感到困惑。但接触它并没有对我产生任何影响,只是激励我真正理解发生了什么。如果我能够弄清楚(至少在某种程度上,比零略微大一点),那么其他人也可以解决它。 - Ferdinand.kraft
2
我认为他们不一定会理解它(尽管这是其中的一部分);我认为这是解决这个问题的错误方式。最好、最惯用的方法是使用列表;getassign是次优的选择:而eval/parse则是第三优的选择。library(fortunes); fortune(106)说:“如果答案是parse(),你通常应该重新考虑问题。(Thomas Lumley)”。有经验的用户曾被parse/substitute的怪异行为所困扰,并学会了除非绝对必要,否则要避免使用它们... - Ben Bolker
@BenBolker,我刚刚安装了 fortunes 包。哈哈。感谢你提供的链接。好吧,我必须承认。我的目标不仅是解决他的问题,也是向他介绍语言中一些很棒的特性。 - Ferdinand.kraft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接