希望我能解释我正在努力做的事情。我有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)
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
我想知道第[i]行的'end_time'(df1)与第[i + 1]行的'start_time'(df1)之间的'Speed'(df2)> 3。如果确实如此,则将“ 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")))
答案 0 :(得分:1)
这也是您可以使用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
中,您是2月11日,在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
的输出,因为只有Speed
> 3的情况为1,并且这不在任何end_time
和下一个{{1}之间}:
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
˛的df1
的第三行替换为end_time
,则会得到:
09:44:00
答案 1 :(得分:0)
首先,为了比较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)
您可以检查它是否有效,最后进行筛选以仅将Speed> 3保留(我不这样做,因为示例数据集中没有Speed> 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