Подстановка строк на основе дат и критериев в двух фреймах данных
У меня есть один фрейм данных, отражающий уровни загрязнения, постоянно измеряемые на двух участках.
Dates <- as.data.frame(seq(as.Date("2015/01/01"), as.Date("2017/01/01"),"day"))
Pollution_Site.A <- as.data.frame(c(seq(from = 1, to = 366, by = 1),
(seq(from = 366, to = 1, by = -1))))
Pollution_Site.B <- as.data.frame(c(seq(from = 0, to = 365, by = 1),
(seq(from = 365, to = 0, by = -1))))
df1 <- cbind(Dates,Pollution_Site.A,Pollution_Site.B)
colnames(df1) <- c("Dates","Site.A","Site.B")
У меня есть отдельный фрейм данных, который подсвечивается, когда геодезисты (на каждом сайте есть один уникальный геодезист) посещают каждый сайт.
Site<- c("Site.A","Site.A","Site.B","Site.B")
Survey_Dates <- as.data.frame(as.POSIXct(c("2014/08/17","2016/08/01",
"2015/02/01","2016/10/31")))
df2 <- as.data.frame(cbind(Site,Survey_Dates))
colnames(df2) <- c("Site","Survey_Dates")
Что я хочу сделать, так это (i) определить событие с высоким уровнем загрязнения (хотя, возможно, лучше использовать некоторую форму функции "Применить" для нескольких итераций)?
High_limit_Site.A <- 1.5*median(df1$Site.A)
High_limit_Site.B <- 1.5*median(df1$Site.B)
Я хочу (ii) установить подмножество второго фрейма данных, чтобы показать, какие геодезисты посещали участок до и после сильного загрязнения в течение 1 года (при условии наличия данных о загрязнении). Я предполагаю, что что-то вроде функции difftime будет работать здесь, но я не уверен, как бы я применил это.
Наконец, я хотел бы (iii) поднабор данных кадра, чтобы выделить, был ли геодезист вне или после события загрязнения.
Таким образом, в приведенном выше примере желаемый результат должен содержать только сайт B. Это потому, что первая дата съемки на участке A предшествует первому измерению загрязнения И была более чем за год до события с высоким уровнем загрязнения. Заранее благодарю за любую помощь в этом.
2 ответа
Вам нужно повернуть df1
а затем соединить его с df2
library(dplyr)
library(tidyr)
df1 %>% gather(key=Site, value=Pollution, -Dates) %>%
group_by(Site) %>%
mutate(HighLimit=as.numeric(Pollution>1.5*median(Pollution))) %>%
filter(HighLimit==1) %>%
# this will function as cross-join because Site is not a unique ID
left_join(df2, by=c("Site")) %>%
mutate(Time_Lag = as.numeric(as.Date(Survey_Dates)-as.Date(Dates)),
Been_Before = ifelse(Time_Lag>0, "after", "before")) %>%
filter(abs(Time_Lag)<365) %>%
group_by(Site, Survey_Dates, Been_Before) %>%
summarise(Event_date_min=min(Dates),
Event_date_max=max(Dates))
Здесь вы можете увидеть самые ранние и последние события, соответствующие каждому посещению
# A tibble: 3 x 5
# Groups: Site, Survey_Dates [?]
Site Survey_Dates Been_Before Event_date_min Event_date_max
<chr> <dttm> <chr> <date> <date>
1 Site.A 2016-08-01 after 2015-10-03 2016-04-01
2 Site.B 2015-02-01 before 2015-10-02 2016-01-30
3 Site.B 2016-10-31 after 2015-11-01 2016-04-02
Просто для того, чтобы использовать ответ @dmi3kno, показанный выше, я могу затем подгруппировать сайты, которые содержат как "до", так и "после" для каждого сайта.
Output_df <- df1 %>% gather(key=Site, value=Pollution, -Dates) %>%
group_by(Site) %>%
mutate(HighLimit=as.numeric(Pollution>1.5*median(Pollution))) %>%
filter(HighLimit==1) %>%
left_join(df2, by=c("Site")) %>%
mutate(Time_Lag = as.numeric(as.Date(Survey_Dates)-as.Date(Dates)),
Been_Before = ifelse(Time_Lag>0, "after", "before")) %>%
filter(abs(Time_Lag)<365) %>%
group_by(Site, Survey_Dates, Been_Before) %>%
summarise(Event_date_min=min(Dates),
Event_date_max=max(Dates))
Затем снова используйте dplyr:
Final_df <- Output_df %>%
group_by(Site) %>%
filter(all(c("before", "after") %in% Been_Before))