从数据框中提取一系列观察数据,以获取完整的数据集

时间:2015-06-08 17:43:20

标签: r loops dataframe pattern-matching subset

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

1)DateTime(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))
          }
    }

1 个答案:

答案 0 :(得分:3)

您的问题可归结为在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

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