Объединить фреймы данных на основе критериев даты в R

#r #dataframe #merge

#r #фрейм данных #объединить

Вопрос:

У меня есть два фрейма данных (скажем, DF1 и DF2). Я хочу объединить их на основе нескольких критериев. Если «штат» и «город» DF1 совпадают с DF2, а «дата» DF2 находится в пределах четырех лет от «даты» DF1, то я хотел бы добавить столбец «margin» из DF2 в DF1. Если условия не будут выполнены, столбец ‘margin’ DF1 будет иметь значение NA.

 DF1 <- structure(list(date = c("2001-02-14", "2001-06-14", "2004-03-31", 
"2003-03-11", "2003-06-29"), state = c("DE", "NY", "NY", "NY", 
"AZ"), city = c("Wilmington", "New York", "Buffalo", "New York", 
"Phoenix"), industry = c("Retail", "Computers and Software", 
"Manufacturing (Misc.)", "Healthcare and Medical", "Construction and Supplies"
), SIC = c(5331, 3571, 2541, 8063, 2421)), row.names = c(2937L, 
2817L, 2117L, 2298L, 2228L), class = "data.frame")

DF2 <- structure(list(date = c("2000-11-07", "2000-11-07", "2008-11-04", 
"2000-11-07", "2000-11-07", "2008-11-04", "2004-11-02", "2004-11-02", 
"2008-11-04", "2012-11-06"), state = c("MA", "NY", "OH", "VA", 
"CA", "DE", "NY", "NY", "NY", "AZ"), city = c("Boston", "New York", 
"Cleveland", "Richmond", "Los Angeles", "Wilmington", "New York", 
"Buffalo", "New York", "Phoenix"), margin = c(-3.61895488477766, -41.5805022156573, -40.2049010106604, 
24.8839947364776, 17.2042747593408, -55.4514285714286, -35.5094126201826, 
-61.9743406985032, -39.9718177548145, 7.47655435915248)), row.names = c(9849L, 
10041L, 29268L, 11941L, 7365L, 31116L, 13227L, 17397L, 23352L, 
32571L), class = "data.frame")
 

Комментарии:

1. В вашем примере все даты находятся в пределах 4 лет

2. также merge ссылается ли столбец margin ? оба требуют уточнения

3. Спасибо @akrun. В моей выборке много наблюдений, поэтому мне пришлось взять случайную выборку. В этой случайной выборке даты могут быть в пределах 4 лет, но в целом это не так.

4. Спасибо @EJJ. Я исправил опечатку.

Ответ №1:

Что-то вроде этого? В зависимости от того, как вы хотите интервал.

  library(lubridate)
 library(fuzzyjoin)
    
        DF1$date <- ymd(DF1$date)     
        DF2$date <- ymd(DF2$date)       
        DF2$interval <- interval(DF2$date,  DF2$date   years(4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        fuzzy_left_join(DF1, DF2, 
                        by = c("city" = "city",
                               "state" = "state",
                               "date" = "interval"),
                        match_fun = c(`==`, `==`, `%within%`))
 

Комментарии:

1. Спасибо @gravertje. С небольшими исправлениями это работает.