R:循环遍历列名

时间:2016-12-25 02:04:50

标签: r dplyr

我是Stata用户,试图切换到R并且通常会让初学者挣扎。我一直在尝试(并且失败)做了几天的循环,现在我投降了。 我想做什么(在一个循环中):

  • 从变量名列表

  • 开始
  • 创建一个新变量

  • 根据现有变量的值重新编码新变量

  • 可能使用dplyr语法这样做,但这不是必需的, 只是为了与我的其余代码保持一致。

这是我想要做的一个程式化的例子。在我的实际数据中,x.x和x.y变量源自应用于2个现有数据帧的连接函数。

N <- 1000
  df  <- data.frame(x1 = rnorm(N),
x2.x = rnorm(N)+2,x2.y = rnorm(N)-2,
x3.x = rnorm(N)+3,x3.y = rnorm(N)-3)

varlist <- c("x2","x3")
lapply(varlist, function(x) {
   df <- df %>% mutate(x = ifelse(x1 < 0, paste0(x,".y"),paste0(x,".x")) # generate varialble "x" values from existing x.x and x.y
  })

当我运行代码的lapply部分时,我收到错误消息

  

错误:意外'}'在:   “df&lt; -df%&gt;%mutate(x = ifelse(x1&lt; 0,paste0(x,”。y“),paste0(x,”。x“))#从现有值生成变量”x“值xx和xy     }“

即使它应该被预期......我确信我的代码中存在许多错误,这部分是因为我习惯于Stata中的宏,而R中没有直接的等价物。无论如何,如果你能指出我正确的方向,这将是太棒了!

3 个答案:

答案 0 :(得分:3)

您的代码无效的原因是您的paste0(x, ".y")确实将x.y粘贴在一起。就是这样,您并没有告诉它按该列对数据进行分组。

您实际应该做的是根据paste0(x, ".y")生成的列名对数据进行子集化。例如,要获取数据列x2.y,您可以去

df[, paste0(varlist[1], ".y")]
## and of course the same can be done for second item of varlist
# df[, paste0(varlist[2], ".y")]

现在我们知道如何通过变量名称对列进行子集,并且因为您想要学习如何在循环中编写它,我们可以用varlist[1](和varlist[2])替换数字&#39;循环&#39;变量

以下是两种方法:一种是使用进行循环,另一种是使用 sapply

For loop

for(i in varlist){
  df[, i] <- ifelse(df[, "x1"] < 0, df[, paste0(i, ".y")], df[, paste0(i, ".x")])
}

head(df)
#            x1       x2.x       x2.y     x3.x       x3.y         x2        x3
# 1 -0.56047565  1.0042013 -2.5116037 2.849693 -2.8034502 -2.5116037 -2.803450
# 2 -0.23017749  0.9600450 -1.7630621 2.672243 -2.3498868 -1.7630621 -2.349887
# 3  1.55870831  1.9820198 -2.5415892 1.551835 -2.3289958  1.9820198  1.551835
# 4  0.07050839  1.8678249 -0.7807724 2.302715 -4.2841578  1.8678249  2.302715
# 5  0.12928774 -0.5493428 -1.8258641 5.598490 -5.0261096 -0.5493428  5.598490
# 6  1.71506499  3.0405735 -2.6152683 2.962585 -0.7946739  3.0405735  2.962585

sapply

您也可以使用*apply执行此操作,在这种情况下,我使用sapply,以便简化&#39;结果(而lapply将返回列表)

df[, varlist] <- sapply(varlist, function(x){
   ifelse(df[, "x1"] < 0, df[, paste0(x, ".y")], df[, paste0(x, ".x")])
})

head(df)
#            x1       x2.x       x2.y     x3.x       x3.y         x2        x3
# 1 -0.56047565  1.0042013 -2.5116037 2.849693 -2.8034502 -2.5116037 -2.803450
# 2 -0.23017749  0.9600450 -1.7630621 2.672243 -2.3498868 -1.7630621 -2.349887
# 3  1.55870831  1.9820198 -2.5415892 1.551835 -2.3289958  1.9820198  1.551835
# 4  0.07050839  1.8678249 -0.7807724 2.302715 -4.2841578  1.8678249  2.302715
# 5  0.12928774 -0.5493428 -1.8258641 5.598490 -5.0261096 -0.5493428  5.598490
# 6  1.71506499  3.0405735 -2.6152683 2.962585 -0.7946739  3.0405735  2.962585

数据

set.seed(123)   ## setting the seed as we're sampling
N <- 1000
df  <- data.frame(x1 = rnorm(N),
                  x2.x = rnorm(N)+2,x2.y = rnorm(N)-2,
                  x3.x = rnorm(N)+3,x3.y = rnorm(N)-3)

答案 1 :(得分:0)

试试这个兄弟

mutate替换为mutate_

https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html

答案 2 :(得分:0)

这对我有用:

lapply(varlist, function(x) 
  df <- df %>% mutate(x = ifelse(x1 < 0, paste0(x,".y"),paste0(x,".x")) # generate varialble "x" values from existing x.x and x.y
))

您不需要使用大括号来指定使用lapply的循环。有关lapply语法的详细信息,请Read this