Как выбрать среди 4 столбцов два последовательных с максимальным диапазоном и разделить его на максимальный диапазон, найденный между любым из 4 столбцов - PullRequest
1 голос
/ 02 апреля 2019

У меня есть df1, который суммирует различные даты и времени и df2, который суммирует различные температуры воды на разных глубинах во времени.Я хочу добавить новый столбец в df1 с именем Prop_rangeT, который для определенной даты и времени равен максимальному диапазону между двумя последовательными столбцами, разделенному между максимальным диапазоном с учетом любого из четырех столбцов в df2 для того же времени и даты, чемdf1.Как пример:

df1<- data.frame(DateTime=c("2016-08-01 08:01:17","2016-08-01 09:17:14","2016-08-01 10:29:31","2016-08-01 11:35:02","2016-08-01 12:22:45","2016-08-01 13:19:27","2016-08-01 14:58:17","2016-08-01 15:30:10"))
df1$DateTime<- as.POSIXct(df1$DateTime, format = "%Y-%m-%d %H:%M:%S", tz= "UTC")
df2<- data.frame(DateTime=c("2016-08-01 08:00:00","2016-08-01 09:00:00","2016-08-01 10:00:00","2016-08-01 11:00:00","2016-08-01 12:00:00","2016-08-01 13:00:00","2016-08-01 14:00:00","2016-08-01 15:00:00"),T5=c(27.0,27.5,27.1,27.0,26.8,26.3,26.0,26.3),T15=c(23.0,23.4,23.1,22.7,22.5,21.5,22.0,22.3),T25=c(19.0,20.0,19.5,19.6,16.0,16.3,16.2,16.7),T35=c(16.0,16.0,16.5,16.7,16.3,16.7,16.9,16.7))
df2$DateTime<- as.POSIXct(df2$DateTime, format = "%Y-%m-%d %H:%M:%S", tz= "UTC")

df1
             DateTime
1 2016-08-01 08:01:17
2 2016-08-01 09:17:14
3 2016-08-01 10:29:31
4 2016-08-01 11:35:02
5 2016-08-01 12:22:45
6 2016-08-01 13:19:27
7 2016-08-01 14:58:17
8 2016-08-01 15:30:10

df2
             DateTime   T5  T15  T25  T35
1 2016-08-01 08:00:00 27.0 23.0 19.0 16.0 # Here max range is between T35 ans T5 (11) and the max range between two consecutive columns is either T15 and T5 or T25 and T15 (4).
2 2016-08-01 09:00:00 27.5 23.4 20.0 16.0
3 2016-08-01 10:00:00 27.1 23.1 19.5 16.5
4 2016-08-01 11:00:00 27.0 22.7 19.6 16.7
5 2016-08-01 12:00:00 26.8 22.5 16.0 16.3
6 2016-08-01 13:00:00 26.3 21.5 16.3 16.7
7 2016-08-01 14:00:00 26.0 22.0 16.2 16.9 # In this case, max range is between T25 and T5 (9.8), and the max range between two consecutive columns correspond to T25 and T15 (5.8).
8 2016-08-01 15:00:00 26.3 22.3 16.7 16.7

Как я могу получить столбец df1$Prop_rangeT с самым простым кодом?В качестве примера того, что я хотел бы получить:

df1
             DateTime Prop_rangeT
1 2016-08-01 08:01:17   0.3636364 # For instance, this is 4/11
2 2016-08-01 09:17:14   0,3565217
3 2016-08-01 10:29:31   0,3773585
4 2016-08-01 11:35:02   0.4174757
5 2016-08-01 12:22:45   0.6018519
6 2016-08-01 13:19:27   0.5200000
7 2016-08-01 14:58:17   0.5918367 # For instance, this is 5.8/9.8
8 2016-08-01 15:30:10   0.5833333

Ответы [ 4 ]

2 голосов
/ 02 апреля 2019

Сначала найдите интересующие нас столбцы для расчета максимального значения (начиная с «T»). Теперь для каждой строки в этих столбцах вычислите отношение максимальной разницы в последовательной стоимости и максимальной разницы в общей стоимости. Сопоставьте отметку времени в df1 и df2 и получите соответствующее соотношение.

t_cols <- grep("^T", names(df2))


df2$ratio <- apply(df2[t_cols], 1, function(x) {
       max_consecutive <- max(-diff(x))
       new_x <- sort(x)
       max_total <- new_x[length(x)] - new_x[1]
       max_consecutive/max_total
})


df1$Prop_rangeT <- df2$ratio[match(lubridate::floor_date(df1$DateTime, "hour"), 
                                                          df2$DateTime)]


df1
#             DateTime Prop_rangeT
#1 2016-08-01 08:01:17   0.3636364
#2 2016-08-01 09:17:14   0.3565217
#3 2016-08-01 10:29:31   0.3773585
#4 2016-08-01 11:35:02   0.4174757
#5 2016-08-01 12:22:45   0.6018519
#6 2016-08-01 13:19:27   0.5200000
#7 2016-08-01 14:58:17   0.5918367
#8 2016-08-01 15:30:10   0.5833333
1 голос
/ 02 апреля 2019
#Assuming that df1 and df2 fit by row 
(df1$Prop_rangeT <- apply(df2[,2:5], 1, function(x) {max(abs(diff(x)))/diff(range(x))}))
#0.3636364 0.3565217 0.3773585 0.4174757 0.6018519 0.5200000 0.5918367 0.5833333

#In case they don't fit by row matching them e.g. by Year, Month, Day and Hour
df1$Prop_rangeT <- apply(df2[,2:5], 1, function(x) {
 max(abs(diff(x)))/diff(range(x))})[match(format(df1$DateTime, "%Y%m%d%H"), format(df2$DateTime, "%Y%m%d%H"))]
1 голос
/ 02 апреля 2019

Мы можем использовать fuzzy_left_join

library(tidyverse)
library(fuzzyjoin)
df1 %>%
    fuzzy_left_join(
        df2 %>%
            gather(key, val, -DateTime) %>%
            group_by(DateTime) %>%
            arrange(DateTime) %>%
            summarise(ratio = max(abs(c(0, diff(val))) / max(abs(diff(combn(x, 2)))))),
        by = "DateTime", match_fun = list(`>`)) %>%
    group_by(DateTime.x) %>%
    filter(DateTime.x - DateTime.y == min(DateTime.x - DateTime.y))
## A tibble: 8 x 3
## Groups:   DateTime.x [8]
#  DateTime.x          DateTime.y          ratio
#  <dttm>              <dttm>              <dbl>
#1 2016-08-01 08:01:17 2016-08-01 08:00:00 0.364
#2 2016-08-01 09:17:14 2016-08-01 09:00:00 0.373
#3 2016-08-01 10:29:31 2016-08-01 10:00:00 0.364
#4 2016-08-01 11:35:02 2016-08-01 11:00:00 0.391
#5 2016-08-01 12:22:45 2016-08-01 12:00:00 0.591
#6 2016-08-01 13:19:27 2016-08-01 13:00:00 0.473
#7 2016-08-01 14:58:17 2016-08-01 14:00:00 0.527
#8 2016-08-01 15:30:10 2016-08-01 15:00:00 0.509

Пояснение: Мы изменяем df2 с широкой на длинную и рассчитываем максимальное отношение (абсолютной) разности температур на последовательных глубинах и максимальной разницы втемпература измеряется на любых глубинах.Остальное - нечеткое объединение на DateTime, где мы выбираем только те записи, которые являются ближайшими по дате для каждого DateTime в df1.

1 голос
/ 02 апреля 2019

Я думаю, что это работает.Ничего особенного здесь не происходит.Я выписал каждое различие, а затем добавил несколько rowwise расчетов.

library(dplyr)
library(lubridate)

df1 %>% 
  mutate(FloorDate = floor_date(DateTime, unit = "hour")) %>% 
  left_join(df2, by = c("FloorDate" = "DateTime")) %>% 
  mutate(ConsDiff1 = abs(T5 - T15),
         ConsDiff2 = abs(T15 - T25),
         ConsDiff3 = abs(T25 - T35),
         AllDiff1 = abs(T5 - T25),
         AllDiff2 = abs(T5 - T35),
         AllDiff3 = abs(T15 - T35)) %>% 
  rowwise() %>% 
  mutate(MaxConsDiff = max(ConsDiff1, ConsDiff2, ConsDiff3),
         MaxAllDiff = max(ConsDiff1, ConsDiff2, ConsDiff3, AllDiff1, AllDiff2, AllDiff3),
         Prop_rangeT = MaxConsDiff / MaxAllDiff) %>% 
  select(DateTime, Prop_rangeT)

# A tibble: 8 x 2
  DateTime            Prop_rangeT
  <dttm>                    <dbl>
1 2016-08-01 08:01:17       0.364
2 2016-08-01 09:17:14       0.357
3 2016-08-01 10:29:31       0.377
4 2016-08-01 11:35:02       0.417
5 2016-08-01 12:22:45       0.602
6 2016-08-01 13:19:27       0.520
7 2016-08-01 14:58:17       0.592
8 2016-08-01 15:30:10       0.583
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...