【问题标题】:R - for loop to compare columns across the same data setR - for 循环比较同一数据集中的列
【发布时间】:2018-04-03 11:48:02
【问题描述】:

我有几个国家连续 2 年的某些经济指标列表。国家是一行,每个经济指标是每一年的一列(V1_2015和V1_2016是我要比较的变量。

我想循环比较变量。幸运的是,这些列的顺序正确,所以我想我可以遍历。我不是 for 循环的专家,但我认为我非常接近......

Economics_2_years <- as.data.frame(cbind(
                    CountryID = c(9999,8888,7777,6666,5555,4444,3333,2222,1111,1234),
                    V1_2015 = c(1,1,1,1,1,1,1,1,1,1),
                    V2_2015 = c(2,2,2,2,2,2,2,2,2,2),
                    V3_2015 = c(3,3,3,3,3,3,3,3,3,3),
                    V1_2016 = c(1,2,1,2,1,2,1,2,1,2),
                    V2_2016 = c(9,1,2,5,3,2,1,2,2,2),
                    V3_2016 = c(0,0,0,0,0,0,0,0,0,0)))


Economics_Change <- as.data.frame(matrix(nrow = 10, ncol = 4))
Economics_Change$V1 <- Economics_Change$CountryID

for (i in 2:4){
for (j in 5:7){
for (k in 2:4)
  Economics_Change[,k]  <- Economics_2_years[,i]==Economics_2_years[,j]

} }

目的是在“Economics_Change”中存储变量是否发生变化。如果他们改变了,哪些改变了。

【问题讨论】:

    标签: r for-loop compare


    【解决方案1】:

    R 是一种矢量化编程语言,因此您可以使用 for 循环代替:

        Economics_Change$V1 <- Economics_2_years$V1_2015==Economics_2_years$V1_2016
        Economics_Change$V2 <- Economics_2_years$V2_2015==Economics_2_years$V2_2016
        Economics_Change$V3 <- Economics_2_years$V3_2015==Economics_2_years$V3_2016
    

    或者如果有很多列,但有一些与它们的名字有些一致的你可以这样做:

    cols <- lapply(1:3, function(var_number) {
      Economics_2_years[paste("V", var_number, "_2015", sep="")] == Economics_2_years[paste("V", var_number, "_2016", sep="")]
    })
     results_df <- do.call("cbind", cols)
    

    如果名称更复杂,则 V + number + _year 或数字带有空格,这里是一个示例,您可以如何处理它。

    Economics_2_years <- as.data.frame(cbind(
      CountryID = c(9999,8888,7777,6666,5555,4444,3333,2222,1111,1234),
      VVV1_2015 = c(1,1,1,1,1,1,1,1,1,1),
      VE7_2015 = c(2,2,2,2,2,2,2,2,2,2),
      V10_2015 = c(3,3,3,3,3,3,3,3,3,3),
      VVV1_2016 = c(1,2,1,2,1,2,1,2,1,2),
      VE7_2016 = c(9,1,2,5,3,2,1,2,2,2),
      V10_2016 = c(0,0,0,0,0,0,0,0,0,0)))
    
    
    colnames(Economics_2_years) %>% regmatches(., gregexpr("^(.*?)_", .)) %>% unlist() %>% unique() -> names_roots
    cols <- lapply(names_roots, function(root) {
      Economics_2_years[paste(root, "2015", sep="")] == Economics_2_years[paste(root, "2016", sep="")]
    })
    results_df <- do.call("cbind", cols)
    

    【讨论】:

    • Pawel - 这是正确的,也是我选择的路线之一;但是,我每年有 85 列。这就是我希望利用循环的原因。
    • 我知道我编辑了我的答案。拉普利呢?对于小的 n 它比 for 循环更快,并且看起来更优雅。我假设列名在某种程度上相似,因此您可以动态更改列名并将我的示例扩展到任意数量的列。如果您的列名不像“V_number_year”那么简单,那么您总是可以获得所有的列名,提取“V”部分,获取它们的唯一向量,并使用lapply轻松适应我的答案。
    • 还有一个问题 - 如果我按照这个示例进行操作,如果数字有差距,我会收到错误消息。如果我有 V1.x、v25.x、v1.y、v25.y,我会收到错误消息。也许我不像我想的那样理解 lapply ......在上面的例子中,我假设 lapply(1:2, ...) 可以工作,但我得到“[.data.frame中的错误@(Conditions_ALL_Wide3, paste("HCC ", var_number, : 选择了未定义的列"
    • 好吧,据我了解,问题是数字不像 1,2,3,4,... 而是 1,25,33,100 等。所以你不能使用 :生成列名的一部分。好的,但是如果它们在“V”、“某个数字”、“_”和那一年之后的方式上是一致的,那么正如我所说,你可以用正则表达式提取第一部分。我将在我的回复中添加示例。
    猜你喜欢
    • 2020-11-04
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2021-09-20
    相关资源
    最近更新 更多