【问题标题】:Looping through variable names in R循环遍历R中的变量名
【发布时间】:2012-12-21 21:16:49
【问题描述】:

我遇到了循环问题。解决起来应该很简单,但是“Stata 用户的 R”(我已经在 Stata 中编码了几年)、Roger Peng 的视频和 Google 似乎并没有帮助我。你们中的一个可以向我解释我做错了什么吗?

我正在尝试编写一个遍历“阈值”数据框的循环,以从三组列中提取信息。我可以通过将同一段代码写三遍来做我想做的事情,但是随着代码变得越来越复杂,这将变得相当繁琐。

这是一个“阈值”示例(请参阅下面的 dput 输出,由友好的读者添加):

    threshold_1_name      threshold_1_dir threshold_1_value
1   overweight            >                25
2   possible malnutrition <                31
3   Q1                    >                998
4   Q1                    >                998
5   Q1                    >                998
6   Q1                    >                998
    threshold_1_units threshold_2_name threshold_2_dir threshold_2_value threshold_2_units
1   kg/m^2            obese               >             30                kg/m^2
2   cm                <NA>                >             NA                   
3   <NA>              Q3                  >             998                  
4                     Q3                  >             998                  
5                     Q3                  >             998                  
6                     Q3                  >             998  

这段代码做了我想做的事:

newvars1 <- paste(thresholds$varname, thresholds$threshold_1_name, sep = "_")
noval <- is.na(thresholds$threshold_1_value)
newvars1 <- newvars1[!noval]

newvars2 <- paste(thresholds$varname, thresholds$threshold_2_name, sep = "_")
noval <- is.na(thresholds$threshold_2_value)
newvars2 <- newvars2[!noval]

newvars3 <- paste(thresholds$varname, thresholds$threshold_3_name, sep = "_")
noval <- is.na(thresholds$threshold_3_value)
newvars3 <- newvars3[!noval]

这是我尝试循环的方式:

variables <- NULL
for (i in 1:3) {
  valuevar <- paste("threshold", i, "value", sep = "_")
  namevar <- paste("threshold", i, "name", sep = "_")
  newvar <- paste("varnames", i, sep = "")
  for (j in 1:length(thresholds$varname)) { 
    check <- is.na(thresholds[valuevar[j]])
    if (check == FALSE) {
      newvars <- paste(thresholds$varname, thresholds[namevar], sep = "_")
    }
  }
  variables <- c(variables, newvars)
}

这是我收到的错误:

Error: unexpected '}' in "}"

我认为我调用“i”的方式有些搞砸了,但我不确定如何正确地做到这一点。当我切换到 R 时,我使用本地人的 Stata 习惯真的让我很恼火。

编辑添加dput 输出,由友好的读者:

thresholds <- structure(list(varname = structure(1:6, .Label = c("varA", "varB", 
"varC", "varD", "varE", "varF"), class = "factor"), threshold_1_name = c("overweight", 
"possible malnutrition", "Q1", "Q1", "Q1", "Q1"), threshold_1_dir = c(">", 
"<", ">", ">", ">", ">"), threshold_1_value = c(25L, 31L, 998L, 
998L, 998L, 998L), threshold_1_units = c("kg/m^2", "cm", NA, 
NA, NA, NA), threshold_2_name = c("obese", "<NA>", "Q3", "Q3", 
"Q3", "Q3"), threshold_2_dir = c(">", ">", ">", ">", ">", ">"
), threshold_2_value = c(30L, NA, 998L, 998L, 998L, 998L), threshold_2_units = c("kg/m^2", 
"cm", NA, NA, NA, NA)), .Names = c("varname", "threshold_1_name", 
"threshold_1_dir", "threshold_1_value", "threshold_1_units", 
"threshold_2_name", "threshold_2_dir", "threshold_2_value", "threshold_2_units"
), row.names = c(NA, -6L), class = "data.frame")

【问题讨论】:

  • 直接的错误是您在for (j in 1:length(thresholds$varname) { 行缺少一个结束括号。
  • @BlueMagister 我看不到。他的代码的第 11 行包含了更接近的内容。
  • @BrandonBertelsen 第 11 行关闭大括号,但 for 语句没有右括号。
  • 您能提供您正在使用的数据框的样本吗?类似于复制粘贴dput(head(thresholds))?请参阅here 以获得良好的可重现示例。

标签: r stata


【解决方案1】:

我看到的第一个问题是在if(check = "FALSE") 中,这是一个赋值=,如果你正在测试一个条件,它必须是==。此外,引用单词"FALSE" 意味着您正在测试字符串值的变量(字面意思是单词FALSE),而不是逻辑值,即FALSE 没有引号。

@BlueMagister 正确指出了第二个问题,您在 for (j in 1:length(...)) { 末尾缺少 )

看到 # 不好!

  for (j in 1:length(thresholds$varname)) { 
    check <- is.na(thresholds[valuevar[j]])
    if (check = "FALSE") { # bad!
      newvars <- paste(thresholds$varname, thresholds[namevar], sep = "_")
    }
  }

看#好!

  for (j in 1:length(thresholds$varname)) { 
    check <- is.na(thresholds[valuevar[j]])
    if (check == FALSE) { # good!
      newvars <- paste(thresholds$varname, thresholds[namevar], sep = "_")
    }
  }

但是因为它是一个 if 语句,所以您可以使用非常简单的逻辑,尤其是在逻辑上(TRUE / FALSE 值)。

看得更清楚!

  for (j in 1:length(thresholds$varname)) { 
    check <- is.na(thresholds[valuevar[j]])
    if (!check) { # better!
      newvars <- paste(thresholds$varname, thresholds[namevar], sep = "_")
    }
  }

【讨论】:

  • 由于check 是逻辑的,"FALSE" 被转换为逻辑。 FALSE=="FALSE" #TRUE
  • 感谢您解释问题。这个解释很清楚也很有帮助!
  • @Struggling_with_R:如果这回答了您的问题,请考虑单击复选标记以向其他用户表明这是最佳答案。
  • @JoshuaUlrich 我不知道!
  • @JoshuaUlrich:我认为是相反的,因为"FALSE"是字符,逻辑check转换为字符,逻辑FALSE然后变成“FALSE”
【解决方案2】:

你的 for 循环中显然缺少一个括号。您应该考虑使用支持大括号匹配的编辑器来避免此类错误。

【讨论】:

    【解决方案3】:

    我认为最简单的做法是编写一个函数来完成您想要的非循环代码的工作。作为参考,这里是该代码的输出,使用编辑您问题的dput 输出。

    > newvars1 <- paste(thresholds$varname, thresholds$threshold_1_name, sep = "_")
    > newvars1 <- newvars1[!is.na(thresholds$threshold_1_value)]
    > newvars2 <- paste(thresholds$varname, thresholds$threshold_2_name, sep = "_") 
    > newvars2 <- newvars2[!is.na(thresholds$threshold_2_value)]
    > c(newvars1, newvars2)
     [1] "varA_overweight"            "varB_possible malnutrition"
     [3] "varC_Q1"                    "varD_Q1"                   
     [5] "varE_Q1"                    "varF_Q1"                   
     [7] "varA_obese"                 "varC_Q3"                   
     [9] "varD_Q3"                    "varE_Q3"                   
    [11] "varF_Q3"  
    

    这是该函数的外观:

    unlist(lapply(1:2, function(k) {
      newvars <- paste(thresholds$varname, 
                       thresholds[[paste("threshold", k, "name", sep="_")]], sep = "_")
      newvars <- newvars[!is.na(thresholds[[paste("threshold", k, "value", sep="_")]])]
    }))
    # [1] "varA_overweight"            "varB_possible malnutrition"
    # [3] "varC_Q1"                    "varD_Q1"                   
    # [5] "varE_Q1"                    "varF_Q1"                   
    # [7] "varA_obese"                 "varC_Q3"                   
    # [9] "varD_Q3"                    "varE_Q3"                   
    #[11] "varF_Q3"  
    

    我试图弄清楚你的循环中发生了什么,但其中有很多对我来说没有意义的东西;如果我要以这种方式循环,这就是我的写法。

    variables <- NULL
    for (i in 1:2) {
      valuevar <- paste("threshold", i, "value", sep = "_")
      namevar <- paste("threshold", i, "name", sep = "_")
      newvars <- c()
      for (j in 1:nrow(thresholds)) { 
        if (!is.na(thresholds[[valuevar]][j])) {
          newvars <- c(newvars, paste(thresholds$varname[j], 
                                      thresholds[[namevar]][j], sep = "_"))
        }
      }
      variables <- c(variables, newvars)
    }
    variables
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-15
      • 2021-01-15
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 2016-01-18
      • 2018-03-07
      • 1970-01-01
      相关资源
      最近更新 更多