使用字符串名称在功能上创建变量

Tur*_*hin 2 string variables r function

我正在尝试生成一个函数,在数据框上创建一堆具有相同命名约定并使用相同逻辑的列.不幸的是,在创建变量时我遇到了一些奇怪的行为,我希望其他人可以解释这里发生了什么.

df <- data.frame(var1 = c(1,2,3), var2 = c(3,4,5), var3 = c("foo", "bar", "baz"))

DoesNotWork <- function(df, varname){
  df[paste(varname, "_square", sep = "")] <- df[varname]^2
  return(df)
}

dfBad <- DoesNotWork(df, "var1")

dfBad
      var1 var2 var3 var1
  1    1    3  foo    1
  2    2    4  bar    4
  3    3    5  baz    9
Run Code Online (Sandbox Code Playgroud)

dfBad这里有两个变量,var1而不是一个被调用的变量var1,一个变量被调用,var1_squared正如我所希望的那样.

下面的函数通过将原始变量的所有值分配给新变量名,然后仅对新变量执行相同操作来解决此问题,但这有点令人讨厌,我不确定会发生什么如果我需要使用多个变量的逻辑.

Works <- function(df, varname){
   df[paste(varname, "_square", sep = "")] <- df[varname]
   df[paste(varname, "_square", sep = "")] <- df[paste(varname, "_square", sep = "")]^2
   return(df)
}

dfGood <- Works(df, "var1")

dfGood
      var1 var2 var3 var1_square
  1    1    3  foo           1
  2    2    4  bar           4
  3    3    5  baz           9
Run Code Online (Sandbox Code Playgroud)

这里的任何指导都将非常感激,特别是如果有一个更好的方法来切换变量名称的字符串和列对象的引用.

jed*_*jed 5

你错过了逗号.

df <- data.frame(var1 = c(1,2,3), var2 = c(3,4,5), var3 = c("foo", "bar", "baz"))

NowItWorks <- function(df, varname){
  df[,paste(varname, "_square", sep = "")] <- df[,varname]^2
  return(df)
}

NowItWorks(df, "var1")

>  var1 var2 var3 var1_square
 1    1    3  foo           1
 2    2    4  bar           4
 3    3    5  baz           9
Run Code Online (Sandbox Code Playgroud)

编辑:好的所以我的上述答案确实有效,但它并没有真正回答第二个问题的原因.

例如:

MultiplicationWorks <- function(df, varname){
  df[paste(varname, "_square", sep = "")] <- df[varname]*2
  return(df)
}
Run Code Online (Sandbox Code Playgroud)

和所有其他非指数运算符一样.如果我们查看data.frame Operators源代码,我们会在底部看到这个有趣的内容:

Ops.data.frame

...
if (.Generic %in% c("+", "-", "*", "/", "%%", "%/%")) {
    names(value) <- cn
    data.frame(value, row.names = rn, check.names = FALSE,
        check.rows = FALSE)
}
else matrix(unlist(value, recursive = FALSE, use.names = FALSE),
    nrow = nr, dimnames = list(rn, cn))
...
Run Code Online (Sandbox Code Playgroud)

基本上这就是说,如果运算符是列出的运算符之一,则返回具有给定名称的data.frame,否则返回具有给定名称的矩阵.出于某种原因,"^"运算符是唯一未列出的运算符.我们可以很容易地证实这一点:

df <- data.frame(var1 = c(1,2,3), var2 = c(3,4,5), var3 = c("foo", "bar", "baz"))

class(df["var1"]*2)

>[1] "data.frame"

class(df["var1"]^2)

>[1] "matrix"
Run Code Online (Sandbox Code Playgroud)

使用exponention,并且只有取幂时,矩阵的dimnames会在分配时覆盖data.frame的新列名.R很奇怪.可笑的是,这意味着您还可以通过包装as.data.frame()指数部分来使代码工作.

如果你想使用你的初始函数看到一些非常奇怪的东西:

? names(dfBad)
[1] "var1"        "var2"        "var3"        "var1_square"
? dfBad
  var1 var2 var3 var1
1    1    3  foo    1
2    2    4  bar    4
3    3    5  baz    9
? str(dfBad)
'data.frame':   3 obs. of  4 variables:
 $ var1       : num  1 2 3
 $ var2       : num  3 4 5
 $ var3       : Factor w/ 3 levels "bar","baz","foo": 3 1 2
 $ var1_square: num [1:3, 1] 1 4 9
  ..- attr(*, "dimnames")=List of 2
  .. ..$ : NULL
  .. ..$ : chr "var1"
Run Code Online (Sandbox Code Playgroud)

R 知道列的正确名称,但会显示您插入其中的矩阵的名称.