Tidyverse: сопоставление конкретных дат с периодами событий - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть даты, которые я хочу сопоставить с событиями, для которых у меня есть только дата начала.В качестве упрощенного примера, скажем, я хотел бы выяснить, кто был президентом во время определенных событий, но у меня есть только даты инаугурации.

pres <- data.frame(pres = c("Ronald Reagan", "George H. W. Bush", 
                            "Bill Clinton", "George W. Bush", "Barack 
                             Obama", "Donald Trump"), 
                     inaugdate = structure(c(4037, 6959, 8420, 11342, 14264, 
                                             17186), class = "Date"))

events <- data.frame(event = c("Challenger explosion", "Chernobyl 
                                explosion", "Hurricane Katrina", "9-11"), 
                      date = structure(c(5871, 5959, 13024, 11576), class = "Date"))

Очевидно, что простой left_join не будет работать, потому что события не 'это может произойти в дни инаугурации.

events %>%
      left_join(pres, by = c("date" = "inaugdate"))

В Excel vlookup используется для предоставления вам значения true (соответствует ближайшему предыдущему) или false (соответствует точному).Есть ли что-то похожее в тидиверсе?

Ответы [ 3 ]

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

Вероятно, не самый эффективный, но мы можем использовать соединение неравенства с sqldf:

library(sqldf)

sqldf('select a.event, a.date, b.pres
      from events a 
      left join pres b
      on a.date >= b.inaugdate
      group by a.event 
      having min(a.date - b.inaugdate)
      order by date, event')

Вывод:

                 event       date           pres
1 Challenger explosion 1986-01-28  Ronald Reagan
2  Chernobyl explosion 1986-04-26  Ronald Reagan
3                 9-11 2001-09-11 George W. Bush
4    Hurricane Katrina 2005-08-29 George W. Bush
0 голосов
/ 05 февраля 2019

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

library(dplyr) 

pres <- data.frame(pres = c("Ronald Reagan", "George H. W. Bush", 
                            "Bill Clinton", "George W. Bush", "Barack Obama", "Donald Trump"), 
                   inaugdate = structure(c(4037, 6959, 8420, 11342, 14264, 
                                           17186), class = "Date")) %>% 
                  #lead date to get interval
                  mutate(enddt = lead(inaugdate, default = Sys.Date())-1)

events <- data.frame(event = c("Challenger explosion", "Chernobyl explosion", "Hurricane Katrina", "9-11"), 
                     date = structure(c(5871, 5959, 13024, 11576), class = "Date"))          
#get every combination of rows
newdf <- merge(pres,events,all = TRUE) %>% 
  filter(date >= inaugdate, date < enddt)
0 голосов
/ 04 февраля 2019

Вот один из способов достижения желаемого результата, хотя, возможно, его можно немного приукрасить.Вы можете создать интервалы, которые являются классом, предоставленным lubridate, чтобы указать промежутки времени с определенным временем начала и окончания.Это происходит с оператором %within%, чтобы увидеть, находится ли дата в этом интервале.Таким образом, мы можем сначала создать этот интервал и сделать столбец pres типом символа, чтобы мы могли правильно его проиндексировать.Затем мы перебираем даты событий с map_chr, используя функцию, которая говорит: «Проверьте, находится ли эта дата в каждом интервале, получите индекс той, в которой она фактически находится (с which), и возвращаем президентав соответствии с этим ".Очевидно, что для этого требуется, чтобы каждая дата находилась только в одном интервале, иначе это не удастся.

library(tidyverse)
library(lubridate)

pres <- data.frame(pres = c("Ronald Reagan", "George H. W. Bush", 
                            "Bill Clinton", "George W. Bush",
                            "Barack Obama", "Donald Trump"), 
                   inaugdate = structure(c(4037, 6959, 8420, 11342, 14264, 
                                           17186), class = "Date"))

events <- data.frame(event = c("Challenger explosion", "Chernobyl explosion",
                               "Hurricane Katrina", "9-11"), 
                     date = structure(c(5871, 5959, 13024, 11576), class = "Date"))

pres2 <- pres %>%
  mutate(
    presidency = interval(inaugdate, lead(inaugdate, default = today())),
    pres = as.character(pres)
  )
events %>%
  mutate(pres = map_chr(date, ~ pres2$pres[which(. %within% pres2$presidency)]))
#>                  event       date           pres
#> 1 Challenger explosion 1986-01-28  Ronald Reagan
#> 2  Chernobyl explosion 1986-04-26  Ronald Reagan
#> 3    Hurricane Katrina 2005-08-29 George W. Bush
#> 4                 9-11 2001-09-11 George W. Bush

Создано в 2019-02-04 пакетом prex (v0.2,1)

...