【问题标题】:Extract series of observations from dataframe for complete sets of data从数据框中提取一系列观察结果以获得完整的数据集
【发布时间】:2015-08-23 07:23:10
【问题描述】:

我有一个由 5 个变量(括号中的类)组成的值的数据框

1)日期时间(as.POSIXct),2)ID(字符),3)传感器 1(数字),4)传感器 2(数字),5)传感器 3(数字)

这些数据是从 5 条带标签的鱼中收集的。每条鱼都有一个标签,上面有 3 个传感器,每个传感器都有一个唯一的 ID(因此 5 条鱼乘以 3 个 ID/标签 = 15 个唯一 ID)。传感器记录彼此相关的测量值,因此同时记录这些测量值。每次都以相同的顺序发送测量数据(ID=A 然后 B 然后 C)。该数据被发送到一次只能接收一个传输的监听接收器。为了避免多个标签同时发送数据并且可能永远不会接收数据,在收集新的一组测量值并重新开始循环之前,每个传感器都会以随机间隔(2-4 分钟之间)发送出去。但是对于随机间隔,有时多个标签会尝试同时发送数据,因此不会记录这些测量值。下面提供了一条鱼的示例数据:

> head(dat,15)

                   DateTime ID  Sensor1 Sensor2  Sensor3
    446 2015-05-15 19:05:41  B       NA    10.2       NA
    464 2015-05-15 19:14:20  B       NA    10.2       NA
    475 2015-05-15 19:17:32  C       NA      NA 10.58824
    486 2015-05-15 19:19:52  A 1.999499      NA       NA
    499 2015-05-15 19:22:31  B       NA    10.2       NA
    515 2015-05-15 19:28:10  A 1.999499      NA       NA
    523 2015-05-15 19:30:56  B       NA    10.1       NA
    542 2015-05-15 19:37:22  A 1.999499      NA       NA
    559 2015-05-15 19:41:09  B       NA    10.2       NA
    574 2015-05-15 19:44:47  C       NA      NA 10.50980
    613 2015-05-15 19:50:23  B       NA    10.3       NA
    633 2015-05-15 19:53:07  C       NA      NA 10.50980
    650 2015-05-15 19:56:32  A 1.999499      NA       NA
    684 2015-05-15 20:02:49  C       NA      NA 10.50980
    702 2015-05-15 20:05:51  A 1.999499      NA       NA

我的问题是尝试仅提取完整的数据集,这意味着在同一循环中为标签检测到 ID 的 A、B 和 C 的循环,因此来自 3 个传感器的数据可以一起使用。如果在一个周期中遗漏了一个 ID,那么我不想要该周期的任何测量值。在上面的示例中,我只想保留一个循环(以数字 542、559 和 574 开头的行。)

一旦我删除了所有不完整的循环,我想将每个循环组合成一个观察结果,这样我就有了一个新的数据框,其中每一行代表一个循环,所有 3 个传感器变量都有值。计算 ID 的 A 和 C 之间的时间也很有用,这样我就可以验证它们来自同一个周期,而不是同一 ID 可能连续多次丢失但顺序仍然有效的情况(机会这种情况的发生率非常非常低)。

到目前为止,我一直在尝试使用 for 循环来提取可以看到正确顺序的 dat 行,并将这些行放入新的数据框中。我不确定如何让 R 将我的标准作为条件语句读取,以及如何在执行我希望循环执行的操作之前满足来自 3 个不同观察的标准。如果可能的话,我很乐意以一种不同于使用循环的方式来做这件事。下面是我的循环示例(我知道我没有调用 True 或 False 值来测试 ==TRUE 条件,我只是不确定如何为每一行执行此操作):

#make blank dataframe    
output <- data.frame (DateTime=rep(as.POSIXct(NA, tz="UTC"), length(tag123o$Transmitter)),
                          ID=rep(as.character(NA), length(tag123o$Transmitter)),
                          Sensor1=rep(as.numeric(NA), length(tag123o$Transmitter)),
                          Sensor2=rep(as.numeric(NA), length(tag123o$Transmitter)),
                          Sensor3=rep(as.numeric(NA), length(tag123o$Transmitter)))

    for (i in 1:length(dat$ID)) {
      if (((dat[i,names(dat)=="ID"] == "A69-1105-123") &
        (dat[i+1,names(dat)=="ID"] == "A69-1105-124") &
          (dat[i+2,names(dat)=="ID"] == "A69-1105-125"))==TRUE) {
            output[i,] <- cbind(dat[i,], data.frame(Cycle=i)) 
            output[i+1,] <- cbind(dat[i+1,], data.frame (Cycle=i))
            output[i+2,] <- cbind(dat[i+2,], data.frame(Cycle=i))
          }
    }

【问题讨论】:

    标签: r loops dataframe pattern-matching subset


    【解决方案1】:

    您的问题归结为在 ID 序列中搜索“ABC”序列:

    (matches <- gregexpr("ABC", paste(dat$ID, collapse=""))[[1]])
    # [1] 8
    # ...
    

    这表示唯一匹配从第 8 行开始。您现在知道 Sensor1 的信息位于编号为 matches 的行中,Sensor2 的信息位于编号为 matches+1 的行中,而 Sensor3 的信息位于编号为编号为matches+2。这使您能够有效地构建所需的数据框,该数据框结合了循环信息:

    data.frame(DateTime1 = dat$DateTime[matches],
               DateTime2 = dat$DateTime[matches+1],
               DateTime3 = dat$DateTime[matches+2],
               Sensor1 = dat$Sensor1[matches],
               Sensor2 = dat$Sensor2[matches+1],
               Sensor3 = dat$Sensor3[matches+2])
    #             DateTime1           DateTime2           DateTime3  Sensor1 Sensor2 Sensor3
    # 1 2015-05-15 19:37:22 2015-05-15 19:41:09 2015-05-15 19:44:47 1.999499    10.2 10.5098
    

    您现在可以进行任何您想要进一步过滤信息的计算(例如,删除测量之间的时间差过大的周期)。

    【讨论】:

      猜你喜欢
      • 2013-07-12
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      • 2016-03-30
      • 2021-04-09
      • 2020-03-26
      相关资源
      最近更新 更多