R найти, если значение в столбце превышает порог между двумя периодами времени от второго df - PullRequest
0 голосов
/ 11 февраля 2019

Надеюсь, я смогу объяснить, что я пытаюсь сделать в достаточной мере.У меня есть df1 со значениями времени начала и окончания деятельности.Однако я хочу использовать это время, чтобы увидеть, превышает ли скорость лодки (df2) определенный порог между двумя промысловыми действиями, чтобы решить, должны ли они быть отдельными видами деятельности (т. Е. Лодка переместилась на новое место) или той же самой деятельностью.

df1 <- data.frame(
vessel_pln=c(rep("AU89",5)),
start_time=c("2018-11-02 05:14:26 GMT","2018-11-02 07:48:16 GMT","2018-11-02 09:03:28 GMT","2018-11-02 10:17:25 GMT","2018-11-05 06:39:12 GMT"),
start_lat=c(55.69713617,55.69693433,55.69539050,55.69043650,55.69103567), 
start_lon=c(-5.65051533,-5.65031783,-5.65317850,-5.65859250,-5.65830600),
end_time=c("2018-11-02 06:54:37 GMT","2018-11-02 08:55:24 GMT","2018-11-02 10:00:14 GMT","2018-11-02 11:55:47 GMT","2018-11-05 08:33:35 GMT"),
end_lat=c(55.69462700,55.69539367,55.69454683,55.69370050,55.69302200),
end_lon=c(-5.65454983,-5.65317550,-5.65567667,-5.65628133,-5.65317550),
activity=c(1,2,3,4,5),
new_activity=c(rep("NO",5)))

библиотека (хрон) tt <- times (1: 200/288) </p>

df2 <- data.frame(
vessel_pln=c(rep("AU89",200)),
GPSTime=c(chron(rep("2/11/18", length = length(tt)), tt)),
Speed=c(runif(200,0,3)))
df2 <- as.POSIXct(df2$GPSTime,format="(%d/%m/%y %H%M%S)",tz="GMT")
df2[108, "Speed"] <- 3.2 

Я хотел бы знать, если «Speed» (df2)> 3 между'end_time' (df1) строки [i] и 'start_time' (df1) строки [i + 1].Если это так, измените столбец «new_activity» (df1) на «YES».

с указанными выше данными, я должен получить следующие результаты:

df3 <- data.frame(
vessel_pln=c(rep("AU89",5)),
start_time=c("2018-11-02 05:14:26 GMT","2018-11-02 07:48:16 GMT","2018-11-02 09:03:28 GMT","2018-11-02 10:17:25 GMT","2018-11-02 16:39:12 GMT"),
start_lat=c(55.69713617,55.69693433,55.69539050,55.69043650,55.69103567), 
start_lon=c(-5.65051533,-5.65031783,-5.65317850,-5.65859250,-5.65830600),
end_time=c("2018-11-02 06:54:37 GMT","2018-11-02 08:55:24 GMT","2018-11-02 10:00:14 GMT","2018-11-02 11:55:47 GMT","2018-11-02 18:33:35 GMT"),
end_lat=c(55.69462700,55.69539367,55.69454683,55.69370050,55.69302200),
end_lon=c(-5.65454983,-5.65317550,-5.65567667,-5.65628133,-5.65317550),
activity=c(1,2,3,4,5),
new_activity=c("NO","NO","YES","NO","NO")))

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Вот также, как вы могли бы подойти к этому с data.table (и немного magrittr для улучшения читабельности);должно быть быстрым даже для больших наборов данных:

library(data.table)
library(magrittr)

col_names <- names(df1)

df1 <- setDT(df1)[, lapply(.SD, as.character)] %>%
  .[, `:=` (end_join = as.POSIXct(end_time),
            start_join = shift(as.POSIXct(start_time), type = "lead")), by = vessel_pln] %>%
  .[is.na(start_join), start_join := as.POSIXct(as.character(end_time))]

df2 <- setDT(df2)[, lapply(.SD, as.character)][, `:=` (GPSTime = as.POSIXct(GPSTime))]

final <- df2[df1, on = .(GPSTime <= start_join, GPSTime >= end_join, vessel_pln = vessel_pln)] %>%
  .[, new_activity := as.character(ifelse(any(Speed > 3), "YES", "NO")), by = activity] %>%
  .[!duplicated(activity), ..col_names] %>%
  .[is.na(new_activity), new_activity := "NO"]

Обратите внимание, что я немного изменил ваш пример данных, так как в противном случае невозможно найти соответствие между датами (в одном df у вас есть 11 февраля,в другое 2 ноября):

library(chron) 

df1 <- data.frame(
  vessel_pln=c(rep("AU89",5)),
  start_time=c("2018-11-02 05:14:26 GMT","2018-11-02 07:48:16 GMT","2018-11-02 09:03:28 GMT","2018-11-02 10:17:25 GMT","2018-11-05 06:39:12 GMT"),
  start_lat=c(55.69713617,55.69693433,55.69539050,55.69043650,55.69103567), 
  start_lon=c(-5.65051533,-5.65031783,-5.65317850,-5.65859250,-5.65830600),
  end_time=c("2018-11-02 06:54:37 GMT","2018-11-02 08:55:24 GMT","2018-11-02 10:00:14 GMT","2018-11-02 11:55:47 GMT","2018-11-05 08:33:35 GMT"),
  end_lat=c(55.69462700,55.69539367,55.69454683,55.69370050,55.69302200),
  end_lon=c(-5.65454983,-5.65317550,-5.65567667,-5.65628133,-5.65317550),
  activity=c(1,2,3,4,5),
  new_activity=c(rep("NO",5)))

tt <- times(1:200/288)

df2 <- data.frame(
  vessel_pln=c(rep("AU89",200)),
  GPSTime=c(chron(rep("11/2/18", length = length(tt)), tt)),
  Speed=c(runif(200,0,3)))

df2$GPSTime <- as.POSIXct(df2$GPSTime,format="(%d/%m/%y %H%M%S)",tz="GMT")
df2[108, "Speed"] <- 3.2 

Теперь результат на самом деле со всеми NO, так как есть только 1 случай с Speed> 3, и он не попадает между end_time и затем start_time:

   vessel_pln              start_time   start_lat   start_lon                end_time     end_lat     end_lon activity new_activity
1:       AU89 2018-11-02 05:14:26 GMT 55.69713617 -5.65051533 2018-11-02 06:54:37 GMT   55.694627 -5.65454983        1           NO
2:       AU89 2018-11-02 07:48:16 GMT 55.69693433 -5.65031783 2018-11-02 08:55:24 GMT 55.69539367  -5.6531755        2           NO
3:       AU89 2018-11-02 09:03:28 GMT  55.6953905  -5.6531785 2018-11-02 10:00:14 GMT 55.69454683 -5.65567667        3           NO
4:       AU89 2018-11-02 10:17:25 GMT  55.6904365  -5.6585925 2018-11-02 11:55:47 GMT  55.6937005 -5.65628133        4           NO
5:       AU89 2018-11-05 06:39:12 GMT 55.69103567   -5.658306 2018-11-05 08:33:35 GMT   55.693022  -5.6531755        5           NO

Однако, если вы измените это немного и замените в 3-й строке df1 *the end_time на 09:44:00, вы получите:

   vessel_pln              start_time   start_lat   start_lon                end_time     end_lat     end_lon activity new_activity
1:       AU89 2018-11-02 05:14:26 GMT 55.69713617 -5.65051533 2018-11-02 06:54:37 GMT   55.694627 -5.65454983        1           NO
2:       AU89 2018-11-02 07:48:16 GMT 55.69693433 -5.65031783 2018-11-02 08:55:24 GMT 55.69539367  -5.6531755        2           NO
3:       AU89 2018-11-02 09:03:28 GMT  55.6953905  -5.6531785 2018-11-02 09:44:00 GMT 55.69454683 -5.65567667        3          YES
4:       AU89 2018-11-02 10:17:25 GMT  55.6904365  -5.6585925 2018-11-02 11:55:47 GMT  55.6937005 -5.65628133        4           NO
5:       AU89 2018-11-05 06:39:12 GMT 55.69103567   -5.658306 2018-11-05 08:33:35 GMT   55.693022  -5.6531755        5           NO
0 голосов
/ 11 февраля 2019

Сначала, чтобы сравнить df1$start_time и df2$GPSTime, вам нужен один и тот же тип для этих двух.

df1$start_time <- as.POSIXct(as.character(df1$start_time),format = "%Y-%m-%d %H:%M:%S", tz="GMT")
df1$end_time <- as.POSIXct(as.character(df1$end_time),format = "%Y-%m-%d %H:%M:%S", tz="GMT")

df2$GPSTime <- as.POSIXct(as.character(df2$GPSTime), format="(%d/%m/%y %H:%M:%S)", tz= 'GMT')

Затем вы можете объединить df1 и df2 и сравнитьдругое время.Затем отфильтруйте, чтобы сохранить хорошие времена.

temp <- df1 %>% 
  left_join(df2, by = 'vessel_pln') %>% 
  mutate(BETWEEN = (GPSTime >= start_time & GPSTime < end_time)) %>% 
  filter(BETWEEN == TRUE)
  #filter(Speed > 3)

Вы можете проверить, сработало ли это, и, наконец, отфильтровать, чтобы сохранить только скорость> 3 (я не делаю это, потому что у меня нет скорости> 3 вмой пример набора данных).

temp %>% 
  filter(activity == 1) %>% 
  select(start_time, end_time, GPSTime, Speed) %>% 
  head()

#            start_time            end_time             GPSTime     Speed
# 1 2018-11-02 05:14:26 2018-11-02 06:54:37 2018-11-02 05:15:00 0.8461418
# 2 2018-11-02 05:14:26 2018-11-02 06:54:37 2018-11-02 05:20:00 0.8610450
# 3 2018-11-02 05:14:26 2018-11-02 06:54:37 2018-11-02 05:25:00 2.8171262
# 4 2018-11-02 05:14:26 2018-11-02 06:54:37 2018-11-02 05:30:00 1.8165029
# 5 2018-11-02 05:14:26 2018-11-02 06:54:37 2018-11-02 05:35:00 2.0697528
# 6 2018-11-02 05:14:26 2018-11-02 06:54:37 2018-11-02 05:40:00 0.5855299
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...