Этот вопрос содержит интересные задачи:
- ОП запрашивает "частичное анти-объединение" , т. Е. ОП хочет объединить текущие данные в
df2
где Datetime
и Site
совпадают, но слой глубины не . - Текущие данные
df2
приведены в справочной таблице, где каждое значение связано с диапазоном глубины (уровень глубины) и интервалом времени из3 часа.Таким образом, измеренные значения Depth
и Datetime
в df1
должны быть сопоставлены с соответствующими диапазонами.
Я пробовал разные подходы, но в итоге я выбрал следующий, который не даетпредположения о агрегатной функции.Таким образом, mean()
можно вызвать напрямую.
library(data.table)
library(magrittr)
# reshape df2 from wide to long format
currents <- melt(setDT(df2), id.vars = c("Datetime", "Site"),
variable.name = "layer", value.name = "current")
# create columns to join on
labels <- names(df2) %>% stringr::str_subset("^m")
breaks <- c(seq(0, 32, 8), Inf)
setDT(df1)[, layer := cut(Depth, breaks = breaks, labels = labels)]
df1[, current.dt := df2[df1, on = .(Site, Datetime),
roll = "nearest", x.Datetime]]
# "partial anti-join" to compute mean of other layers
currents_other_layers <-
currents[df1, on = .(Site, Datetime = current.dt)][
layer != i.layer, mean(current), by = .(i.Datetime, Site)]
# append result column
df1[currents_other_layers, on = .(Site, Datetime = i.Datetime), current.mean := i.V1]
df1
Datetime Site Ind Depth layer current.dt current.mean
1: 2016-08-01 15:34:07 BD 16 5.3 m0-7 2016-08-01 15:00:00 3.7500
2: 2016-08-01 16:25:16 HG 17 24.0 m16-23 <NA> NA
3: 2016-08-01 17:29:16 BD 19 36.4 m32-39 2016-08-01 18:00:00 5.9375
4: 2016-08-01 18:33:16 BD 16 42.0 m32-39 2016-08-01 18:00:00 5.9375
5: 2016-08-01 20:54:16 BD 17 NA <NA> 2016-08-01 21:00:00 NA
6: 2016-08-01 22:48:16 BD 16 22.1 m16-23 2016-08-02 00:00:00 2.8750
Воспроизводит ожидаемый результат OP.
Пояснение
df2
изменен с широкого на длинный формат.Это позволяет объединять / не объединять столбец layer
.
currents
Datetime Site layer current
1: 2016-08-01 12:00:00 BD m0-7 2.75
2: 2016-08-01 15:00:00 BD m0-7 4.00
3: 2016-08-01 18:00:00 BD m0-7 6.75
4: 2016-08-01 21:00:00 BD m0-7 2.25
5: 2016-08-02 00:00:00 BD m0-7 4.30
6: 2016-08-01 12:00:00 BD m8-15 3.00
7: 2016-08-01 15:00:00 BD m8-15 4.00
8: 2016-08-01 18:00:00 BD m8-15 4.75
9: 2016-08-01 21:00:00 BD m8-15 3.00
10: 2016-08-02 00:00:00 BD m8-15 2.10
11: 2016-08-01 12:00:00 BD m16-23 2.75
12: 2016-08-01 15:00:00 BD m16-23 4.00
13: 2016-08-01 18:00:00 BD m16-23 5.75
14: 2016-08-01 21:00:00 BD m16-23 2.25
15: 2016-08-02 00:00:00 BD m16-23 1.40
16: 2016-08-01 12:00:00 BD m24-31 3.25
17: 2016-08-01 15:00:00 BD m24-31 3.00
18: 2016-08-01 18:00:00 BD m24-31 6.50
19: 2016-08-01 21:00:00 BD m24-31 2.75
20: 2016-08-02 00:00:00 BD m24-31 3.40
21: 2016-08-01 12:00:00 BD m32-39 3.00
22: 2016-08-01 15:00:00 BD m32-39 4.00
23: 2016-08-01 18:00:00 BD m32-39 4.75
24: 2016-08-01 21:00:00 BD m32-39 3.00
25: 2016-08-02 00:00:00 BD m32-39 1.70
Datetime Site layer current
Теперь необходимо изменить df1
, добавив в него столбцы, соответствующие layer
и Datetime
в currents
.
Для Depth
используется функция cut()
.Уровень последнего слоя m32-39
расширен до Inf
, поэтому все глубины, превышающие 32 м, включены в этот уровень в соответствии с требованием OP.
Для Datetime
- подвижное соединение с ближайшим Datetime
в df2
используется.Это возможно, потому что df2$Datetime
обозначает середину 3-часового временного диапазона.
После того, как df1
было подготовлено, мы можем выполнить «частичное анти-объединение».К сожалению, неуравновешенные объединения data.table
не принимают оператор !=
.Таким образом, мы не можем написать
currents[df1, on = .(Datetime = current.dt, Site, layer != layer)]
напрямую, но должны использовать обходной путь, в котором мы сначала выбираем строки, в которых ожидаем совпадения, а затем выполняем анти-объединение:
currents[df1, on = .(Datetime = current.dt, Site)][
!df1, on = .(Datetime = current.dt, Site, layer)]
Datetime Site layer current i.Datetime Ind Depth i.layer
1: 2016-08-01 15:00:00 BD m8-15 4.00 2016-08-01 15:34:07 16 5.3 m0-7
2: 2016-08-01 15:00:00 BD m16-23 4.00 2016-08-01 15:34:07 16 5.3 m0-7
3: 2016-08-01 15:00:00 BD m24-31 3.00 2016-08-01 15:34:07 16 5.3 m0-7
4: 2016-08-01 15:00:00 BD m32-39 4.00 2016-08-01 15:34:07 16 5.3 m0-7
5: 2016-08-01 18:00:00 BD m0-7 6.75 2016-08-01 17:29:16 19 36.4 m32-39
6: 2016-08-01 18:00:00 BD m8-15 4.75 2016-08-01 17:29:16 19 36.4 m32-39
7: 2016-08-01 18:00:00 BD m16-23 5.75 2016-08-01 17:29:16 19 36.4 m32-39
8: 2016-08-01 18:00:00 BD m24-31 6.50 2016-08-01 17:29:16 19 36.4 m32-39
9: 2016-08-01 18:00:00 BD m0-7 6.75 2016-08-01 18:33:16 16 42.0 m32-39
10: 2016-08-01 18:00:00 BD m8-15 4.75 2016-08-01 18:33:16 16 42.0 m32-39
11: 2016-08-01 18:00:00 BD m16-23 5.75 2016-08-01 18:33:16 16 42.0 m32-39
12: 2016-08-01 18:00:00 BD m24-31 6.50 2016-08-01 18:33:16 16 42.0 m32-39
13: 2016-08-01 21:00:00 BD m0-7 2.25 2016-08-01 20:54:16 17 NA <NA>
14: 2016-08-01 21:00:00 BD m8-15 3.00 2016-08-01 20:54:16 17 NA <NA>
15: 2016-08-01 21:00:00 BD m16-23 2.25 2016-08-01 20:54:16 17 NA <NA>
16: 2016-08-01 21:00:00 BD m24-31 2.75 2016-08-01 20:54:16 17 NA <NA>
17: 2016-08-01 21:00:00 BD m32-39 3.00 2016-08-01 20:54:16 17 NA <NA>
18: 2016-08-02 00:00:00 BD m0-7 4.30 2016-08-01 22:48:16 16 22.1 m16-23
19: 2016-08-02 00:00:00 BD m8-15 2.10 2016-08-01 22:48:16 16 22.1 m16-23
20: 2016-08-02 00:00:00 BD m24-31 3.40 2016-08-01 22:48:16 16 22.1 m16-23
21: 2016-08-02 00:00:00 BD m32-39 1.70 2016-08-01 22:48:16 16 22.1 m16-23
22: <NA> HG <NA> NA 2016-08-01 16:25:16 17 24.0 m16-23
Datetime Site layer current i.Datetime Ind Depth i.layer
Может быть агрегировано произвольно с помощью произвольной функции агрегирования (не нужно вручную добавлять отдельные столбцы):
currents_other_layers <-
currents[df1, on = .(Datetime = current.dt, Site)][
!df1, on = .(Datetime = current.dt, Site, layer)][
!is.na(Depth), mean(current), by = .(i.Datetime, Site)]
currents_other_layers
i.Datetime Site V1
1: 2016-08-01 15:34:07 BD 3.7500
2: 2016-08-01 17:29:16 BD 5.9375
3: 2016-08-01 18:33:16 BD 5.9375
4: 2016-08-01 22:48:16 BD 2.8750
5: 2016-08-01 16:25:16 HG NA
ЭтоРезультат содержит средние токи всех других слоев, кроме наблюдаемого слоя.Обратите внимание, что группировка производится по i.Datetime
, что относится к df1$Datetime
и Site
.Строки, в которых Depth
отсутствует в df1
, не соответствуют ожидаемому результату OP.
Финальное объединение обновлений добавляет столбец результатов к df1
.