【问题标题】:For() loop to ID dates that are between others and calculate a mean valueFor() 循环到其他日期之间的 ID 日期并计算平均值
【发布时间】:2013-09-22 12:22:40
【问题描述】:

这是“R:For() 循环检查日期是否在单独对象中的两个日期之间”的重新发布,在 Henrik 和 Metrics 的建议下,该内容已更改为包含模拟/测试最小值。感谢他们。

我有两个大型数据集,都包含日期/时间字段列。我的第一个数据集有一个日期,第二个有两个日期。简而言之,我试图从第一个数据集中找到第二个其他两个日期之间的所有日期,然后找到一个平均值。为了清楚起见,我使用值而不是日期创建了一个模拟最小数据集。

下面是我的第一个模拟数据集的 head() 以及 dput() 输出。数据特定于 IndID 列中注明的个人。

  IndID MockDate RandNumber
1     1        5   1.862084
2     1        3   1.103154
3     1        5   1.373760
4     1        1   1.497397
5     1        1   1.319488
6     1        3   2.120354

actData <- structure(list(IndID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L), MockDate = c(5L, 3L, 5L, 1L, 1L, 3L, 4L, 
2L, 2L, 5L, 2L, 1L, 5L, 3L, 5L, 3L, 5L, 3L, 5L, 1L, 5L, 3L, 5L, 
5L, 2L, 3L, 1L, 4L, 3L, 3L), RandNumber = c(1.862083679, 1.103154127, 
1.37376001, 1.497397482, 1.319487885, 2.120353884, 1.895660195, 
1.150411874, 2.61036961, 1.99354158, 1.547706758, 1.941501873, 
1.739226419, 2.455590044, 2.907382515, 2.110502618, 2.076187012, 
2.507527308, 2.167657681, 1.662405916, 2.428807116, 2.04699653, 
1.937335768, 1.456518889, 1.948952907, 2.104325112, 2.311519732, 
2.092650229, 2.109051215, 2.089144475)), .Names = c("IndID", 
"MockDate", "RandNumber"), class = "data.frame", row.names = c(NA, 
-30L))

我的第二个模拟数据集的 head() 以及 dput() 输出如下。

 IndID StartTime EndTime
1     1         4       5
2     1         7      11
3     1         6       9
4     1         7       9
5     1         6      10
6     1         2      12

clstrData <- structure(list(IndID.1 = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L), StartTime = c(4L, 7L, 
6L, 7L, 6L, 2L, 6L, 4L, 3L, 5L, 2L, 5L, 7L, 3L, 4L, 3L, 2L, 5L, 
5L), EndTime = c(5L, 11L, 9L, 9L, 10L, 12L, 8L, 13L, 5L, 13L, 
9L, 9L, 17L, 6L, 8L, 6L, 9L, 15L, 7L)), .Names = c("IndID", 
"StartTime", "EndTime"), row.names = c(NA, 19L), class = "data.frame")

第二个数据集有两个数字字段,分别代表开始时间和结束时间。如上所述,这些数据也特定于 IndD 列中提到的个人。

当“MockDate”在每个唯一 IndID 的第二个数据集的“StartTime”和“EndTime”之间时,我需要对所有实例的数据集一的“RandNumber”进行平均。因此,“RandNumber”值仅应在 1)它们在“StartTime”和“EndTime”内以及 2)两行的 IndID 相同的情况下进行平均。

如果 MockDate 介于 StartTime 和 EndTime 之间,我首先创建一个 ID 函数

is.between <- function(x, a, b) {
    x > a & x < b
}

测试该函数是否适用于单个值 is.between(actData[1,3], clstrData[,2], clstrData[,3])

但无法弄清楚如何对所有行进行循环,然后找到平均值。我的 for() 循环开始如下。

YesNo <- list()
for (i in 1:nrow(actData)) {
YesNo[[i]] <- is.between(actData[1,3], clstrData[,2], clstrData[,3])
}
YesNo[[3]]

这个 for() 对所有行给出相同的结果...

希望创造... clstrData$NEWcolum

谢谢,我们非常感谢任何建议!

【问题讨论】:

    标签: r for-loop


    【解决方案1】:

    感谢 Ricardo Saporta 早期的想法。

    但是,在我的 for() 循环中构造一个长条件对我来说是最好的选择 - 尽管不如 data.table() 快。

    使用上面的数据,下面的代码是我最终构建的。

    clstrData$meanAct = rep(NA, nrow(clstrData))
    
    for (i in 1:nrow(clstrData)){
        clstrData$meanAct[i] = mean(actData$RandNumber[actData$IndID==clstrData$IndID[i]
        &is.between(actData$RandNumber, clstrData$StartTime[i], clstrData$EndTime[i])])
        }
    head(clstrData)
    tail(clstrData)
    

    如果开始时间和结束时间之间没有对应的值,则生成 NAN。

    【讨论】:

      【解决方案2】:

      假设你的机器可以处理数据大小,你可以:

      • 合并ID上的两个数据框,然后
      • 相应分组(即按 IndID、开始和结束日期)
      • 计算模拟日期介于结束日期之间的那些行的平均值

      这是一些使用data.table的代码

      library(data.table)
      DT.clstr <- data.table(clstrData, key="IndID")
      DT.act   <- data.table(actData, key="IndID")
      
      # Adjust to `<=` if needed
      ComputedDT <- 
        merge(DT.clstr, DT.act, allow.cartesian=TRUE)[
            MockDate > StartTime &  MockDate < EndTime
          , list(Mean=mean(RandNumber))
          , by=list(IndID, StartTime, EndTime)
          ]
      

      结果

      ComputedDT
      
         IndID StartTime EndTime     Mean
      1:     1         2      12 1.671002
      2:     2         4      13 2.176799
      3:     2         2       9 2.244702
      4:     3         3       6 1.978828
      5:     3         4       8 1.940887
      6:     3         2       9 2.033104
      

      【讨论】:

      • 酷。查看 ?data.table,pkg 看起来很新。感谢分享。您的代码似乎工作正常,但我丢失了一些结果。最终表需要有 ClstrData 的所有行。我想如果我为每个集群创建一个唯一的 ID,[使用 clstrData$ClstrID
      • @user2778289 查看?merge.data.table 的文档,特别是在参数all.x 中,听起来您想将其设置为TRUE。要捕获没有匹配“中间”日期的 ID/时间,您可能希望创建一个包装函数,如果有值则运行 mean,否则如果没有值则返回 NA。 -- 如果您在第二部分需要帮助,请随时提出新问题
      猜你喜欢
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 1970-01-01
      • 2013-02-25
      • 2018-10-25
      • 1970-01-01
      • 2021-01-16
      • 2019-07-12
      相关资源
      最近更新 更多