Вычислить разницу между значениями с почти идентичной меткой времени



Пожалуйста, рассмотрите эти входные данные:




  • у меня есть два инструмента (41 и 54).

  • Они оба измеряют давление в нескольких резервуарах (T1 и T2).
    Они измеряют давление почти одновременно, но не совсем точно.

Пример данных:



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


Есть идеи, как правильно выполнить эту задачу?
654   1  
r

1 ответ:

Вы можете легко выполнить самосоединение качения на двух подмножествах как на tank, так и на time, что не потребует никакой начальной переупорядоченности при задании максимального интервала качения (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]

Но если вы хотите получить точный желаемый формат, я боюсь, что это потребует некоторого плавления / 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           

Comments

    Ничего не найдено.