【问题标题】:How to do iterations in R?如何在 R 中进行迭代?
【发布时间】:2016-08-12 16:19:12
【问题描述】:

我正在使用一个数据集,该数据集包含不同时间点的相同变量的值。在下面的示例中,我有变量 a 和 b 在时间点 1 和 2 的值。

> set.seed(1)
> data <- data.frame(matrix(sample(16), ncol = 4))
> names(data) <- paste(rep(c("a", "b"), each = 2), 1:2, sep = "")
> data
  a1 a2 b1 b2
1  5  3 14 13
2  6 10  1  8
3  9 11  2  4
4 12 15  7 16

现在,假设我想为两个时间点计算一个新变量,以便它包含 a 和 b 的总和(而不是下面示例中的 NA)。由于我的实际数据集包含大约 15 个不同的变量和 10 个时间点(所以 150 列),我想自动计算 10 个新变量。

> data[, paste("ab", 1:2, sep = "")] <- NA
> data
  a1 a2 b1 b2 ab1 ab2
1  5  3 14 13  NA  NA
2  6 10  1  8  NA  NA
3  9 11  2  4  NA  NA
4 12 15  7 16  NA  NA

我以前使用过 Stata,我可以创建一个简单的“foreach”循环来执行此操作。如下所示。

foreach t of numlist 1/2 {
    generate ab`t' = a`t' + b`t'
}

但我知道在 R 中使用循环是不可行的,我也不知道如何循环像在 R 中那样的变量名。

那么对于我在 R 中的问题,正确的解决方案是什么?

【问题讨论】:

  • 您还可以考虑将数据转换为长格式。像这样,它不是整齐的数据,因为您在列名中有信息。
  • @Heroka 我实际上将数据重新整形为宽格式,因为它看起来更易于操作。但是你说的不整洁是对的,所以我可能会重新考虑。
  • 您的问题/问题似乎与其说是关于迭代,不如说是关于 Stata 在循环中将变量粘贴到名称中的紧凑语法。 (即for(i in 1:2) {}在R中完成同样的循环
  • @jaimedash 我的 Stata 解决方案只是一个示例。由于根据 R 中不推荐使用“Internet”循环,我实际上是在寻找一种不涉及循环但其他迭代方式(例如使用应用和/或函数)的解决方案。

标签: r loops iteration


【解决方案1】:

这将复制您在 Stata 中使用的相同 foreach 循环。

for(i in 1:2){
  data[, paste("ab", i, sep="")] <- 
    data[,paste("a", i, sep="")] + data[, paste("b", i, sep="")]
}

输出如下所示:

> data
  a1 a2 b1 b2 ab1 ab2
1 15  1 16 12  31  13
2 10  7 14  3  24  10
3  2  5  9  4  11   9
4  6  8 13 11  19  19

【讨论】:

  • 我尝试了一个循环,但无法弄清楚如何使用这样的循环变量来引用列。谢谢!
  • 你可以用paste0(...)代替paste( ..., sep="")
【解决方案2】:

要做到这一点R 方式,

  1. 通过*apply 函数使用一些本机迭代
  2. 使用内置的rowSums(如@Sotos)答案
  3. 利用赋值到data.frame,即`]`

大家一起

data[paste0('ab', 1:2)] <- sapply(1:2,
                                  function(i)
                                     rowSums(data[paste0(c('a', 'b'), i)]))
data

#   a1 a2 b1 b2 ab1 ab2
# 1  5  3 14 13  19  16
# 2  6 10  1  8   7  18
# 3  9 11  2  4  11  15
# 4 12 15  7 16  19  31

ps,在程序中使用 vapply 代替,您需要提供一个额外的参数来指定输出的形状,但它更安全,有时更快

【讨论】:

    【解决方案3】:

    你可以不用迭代:

    data$ab1 <- data$a1 + data$b1
    data$ab2 <- data$a2 + data$b2
    

    或

    data <- transform(data, ab1=a1+b1, ab2=a2+b2)
    

    顺便说一句:
    最好不要将对象命名为data,因为data= 通常是函数中的参数。

    【讨论】:

    • 我知道我可以不进行迭代,但一直在寻找更复杂的解决方案(并在此过程中学到一些东西)。如前所述,我的原始数据集在 10 个时间点有大约 15 个变量的值,所以如果我只是输入每个计算,我的 R 代码会变得非常混乱。
    • 好的,对于更复杂的情况,我给出了链接stackoverflow.com/questions/36432686/… Herka 给出了另一个提示:重塑为长格式。 (或者在你的情况下:不适应宽格式。)
    【解决方案4】:

    这是一种方法。我们遍历列名的唯一值,并在这些唯一值与 colname 值匹配时计算 rowSums。

    sapply(unique(sub('\\D', '', names(data))), 
                 function(i) rowSums(data[,grepl(i, sub('\\D', '', names(data)))]))
    #      1  2
    #[1,] 17 23
    #[2,] 24 22
    #[3,] 14 10
    #[4,] 15 11
    

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 2011-02-09
      • 2015-02-22
      • 1970-01-01
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 2015-04-21
      相关资源
      最近更新 更多