计算接近时间戳的值之间的差异

3
请考虑以下输入数据:
  • 我有两个仪器(4154)。
  • 它们都测量几个罐的压力(T1T2)。
  • 它们几乎同时测量压力,但不完全相同。

示例数据:

data  <- data.table(
   time = as.POSIXct(paste("2017-01-01", c("11:59", "12:05", "12:02", "12:03", "14:00", "14:01", "14:02", "14:06")), tz = "GMT"),
   instrumentId = c(41, 54, 41, 54, 41, 54, 41, 54),
   tank = c("T1", "T1", "T2", "T2", "T1", "T1", "T2", "T2"),
   pressure = c(25, 24, 35, 37.5, 22, 22.2, 38, 39.4))

我想计算仪器41测量和仪器54测量的压力差,对于每个罐,假设在20分钟内测得的值属于同一样本。

理想情况下,差值的时间戳将是两个比较值的时间戳的平均值。

到目前为止,我使用了以下脚本:

## Calculate difference of time between 2 consecutive lines
data <- data[, timeDiff := difftime(time, shift(time, type = "lag", fill = -Inf), tz = "GMT", units = "mins"),
                     by = tank]

# Assign the same timestamp to all the measures of a same sample
referenceTimes <- data[timeDiff > 20, .(time)]
data <- data[timeDiff < 20, time := referenceTimes]

# Calculate the difference between the values measured by both instruments
wideDt <- dcast.data.table(data,time + tank ~ instrumentId, value.var = c( "pressure"))
instruments <- as.character(unique(data$instrumentId))
wideDt <- wideDt[, difference := get(instruments[1]) - get(instruments[2])]

它能完成任务,但它最大的问题在于数据必须按适当的方式排序,否则时间偏移计算将返回无意义的结果。使用示例输入数据是可以的,但尝试使用data <- data[order(pressure)]这样的方法“取消排序”。在这种情况下,应添加data <- data[order(tank, time, instrumentId)]
此外,我觉得它可以更简洁、更高效、更清晰。换句话说,它可以更好地利用data.table的优势。
预期结果为:
time                 tank  41   54    difference
-------------------------------------------------
2017-01-01 11:59:00  T1    25   24.0   1.0
2017-01-01 12:02:00  T2    35   37.5  -2.5
2017-01-01 14:00:00  T1    22   22.2  -0.2
2017-01-01 14:02:00  T2    38   39.4  -1.4

有什么办法可以正确执行这项任务吗?

你可以将每个“时间”分组为20分钟的间隔(findInterval(data$time, seq(data$time[1], data$time[nrow(data)], by = "20 mins"))),并应用diff(pressure)按该间隔和“罐”进行分组。 - alexis_laz
@Cath 如果你不认同那个重复问题,请不要打标签。我也没有打上“重复”的标签,因为我不能百分之百确定。 - akrun
即使原帖作者将对象命名为wideDt,@Cath。 - akrun
1
现在我明白这不是重复的了。我会删除那个链接。 - akrun
1个回答

5

您可以轻松地在tanktime上对两个子集执行连续自连接操作,而无需进行任何初始重新排序,同时指定最大滚动间隔(20分钟= 20 * 60秒)。

res <- 
 data[instrumentId == 54, .SD[data[instrumentId == 41], on = .(tank, time), roll = -20*60]]
res
#                   time instrumentId tank pressure i.instrumentId i.pressure
# 1: 2017-01-01 11:59:00           54   T1     24.0             41         25
# 2: 2017-01-01 12:02:00           54   T2     37.5             41         35
# 3: 2017-01-01 14:00:00           54   T1     22.2             41         22
# 4: 2017-01-01 14:02:00           54   T2     39.4             41         38

接下来,计算差值只需要使用res[, difference := pressure - i.pressure]即可。

但如果您想要精确的格式,则需要进行一些melting/dcasting操作。

res2 <-
  dcast(
    melt(res, c("time", "tank"), 
         measure = patterns("instrumentId", "pressure")),
    time + tank ~ value1, value.var = "value2"
        )[, difference := `41` - `54`]

res2
#                   time tank 41   54 difference
# 1: 2017-01-01 11:59:00   T1 25 24.0        1.0
# 2: 2017-01-01 12:02:00   T2 35 37.5       -2.5
# 3: 2017-01-01 14:00:00   T1 22 22.2       -0.2
# 4: 2017-01-01 14:02:00   T2 38 39.4       -1.4           

谢谢。roll是我不知道的功能。 - Blacksad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接