【问题标题】:R: looping through column namesR:遍历列名
【发布时间】:2016-12-25 02:04:50
【问题描述】:

我是一名 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 % mutate(x = ifelse(x1

即使它应该是意料之中的......我确信我的代码中有很多错误,这部分是因为我习惯了 Stata 中的宏,而 R 中没有直接对应的宏。无论如何,如果可以的话为我指明正确的方向,那会很棒!

【问题讨论】:

  • 您在mutate( ... ) 调用的末尾缺少一个右括号。也就是说,你有 4x ( 而只有 3x )
  • 错误信息告诉你}是意外的;它不是应该在的地方。
  • 你在追求df$x2 &lt;- ifelse(df$x1 &lt; 0, df$x2.y, df$x2.x)这样的东西吗?
  • 是的。但使用循环并可能使用 dplyr 语法
  • 你绝对使用循环吗?一个简单的df[, varlist] &lt;- c(ifelse(df$x1 &lt; 0, df$x2.y, df$x2.x), ifelse(df$x1 &lt; 0, df$x3.y, df$x3.x)) 什么时候可以完成这项工作?

标签: r dplyr


【解决方案1】:

您的代码不起作用的原因是您的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])中的数字替换为“循环”变量

这里有两种方法,一种使用 for 循环,另一种使用 sapply

for循环

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

应用

您也可以使用*apply 执行此操作,在本例中我使用sapply 以便“简化”结果(而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)

【讨论】:

  • 谢谢!您的代码运行良好。我知道这有点要求,但你知道如何使用 dplyr 语法做同样的事情吗?
  • 我尝试了以下代码: set.seed(123) ## 在采样时设置种子 N % mutate_(x = ifelse("x1"
  • @mariodrumblue 我从不喜欢在循环中使用dplyr 语法,尤其是在使用动态创建的变量名时。请参阅 this answer 了解我为什么避免使用它的示例。
【解决方案2】:

试试这个兄弟

mutate 替换为mutate_

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

【讨论】:

  • 谢谢!我试过了,它几乎给了我想要的东西,除了我得到 i) 一个名为 x 的新变量(而它应该是 x2 或 x3,具体取决于循环中 x 的值)和 ii) 虽然我可以看到打印输出在控制台上,df 数据框仍然没有改变。我错过了什么?这是代码:
  • lapply(varlist, function(x) df % mutate_(x = ifelse("x1"
【解决方案3】:

这对我有用:

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 指定循环。 Read this 了解更多关于 lapply 语法的信息。

【讨论】:

  • 谢谢。我看到了问题。但是,我仍然没有得到我想要的:
  • 谢谢。我看到了问题。但是,我仍然没有得到我想要的:使用您的代码,我得到 i)一个名为 x 的新变量(而它应该是 x2 或 x3,具体取决于循环中 x 的值)和 ii)给 x 的值是x2.x 或 x2.y(虽然它应该是与这些变量相对应的数值),以及 iii) 虽然我可以在控制台上看到打印输出,但 df 数据框仍然没有改变。有什么提示吗?很抱歉有很多问题。马里奥
猜你喜欢
  • 1970-01-01
  • 2016-09-19
  • 2014-09-26
  • 2018-09-28
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多