2017-09-11 1 views
2

나는 "소유자"라고하는 제휴 자와 날짜가있는 전자 메일 목록을 받아서 날짜와 값이있는 수신 오더와 비교합니다. 일치하는 키는 이메일이지만 가장 가까운 날짜에 일치하는 것을 원합니다. 이메일 주소에 2 명의 다른 소유자가있는 경우도 있습니다.가장 가까운 날짜를 기준으로 매핑

재현 예 :

require(dplyr) 

e <- c("[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]") 
d <- c("2017-01-01", "2017-04-05", "2017-04-12", "2017-05-05", "2017-08-05", "2017-12-05") 
p <- c("Jeff", "Sam", "Sam", "Jeff", "Matt", "Matt") 
df <- data_frame(e, d, p) %>% mutate(d=as.Date(d)) 

o <- c("[email protected]", "[email protected]", "[email protected]", "[email protected]") 
d2 <- c("2017-02-02", "2017-04-28", "2017-05-05", "2017-07-01") 
a <- c(600.50, 3000, 4999.99, 2050.6) 
df2 <- data_frame(o, d2, a) %>% mutate(d2 = as.Date(d2)) 

첫 DF 이메일 주소의지도 p 사람이 소유하고있다. df2은 해당 전자 메일 주소와 함께 제공된 주문이며 에 할당 된 해당 전자 메일 주소를 가진 사람이 올바른 "소유자"를 핀으로 연결하는 df2에 열을 추가하고 싶습니다.

원하는 결과는 :

> df2 
# A tibble: 4 x 3 
       o   d2  a  newowner 
      <chr>  <date> <dbl>  <char> 
1 [email protected] 2017-02-02 600.50  "Jeff" 
2 [email protected] 2017-04-28 3000.00  "Sam" 
3 [email protected] 2017-05-05 4999.99  NA 
4 [email protected] 2017-07-01 2050.60  "Jeff" 

현재는 엄청난 문제가되지 않습니다 - "소유"이메일 주소의 70K 기록에서, 복제 만 ~ 86가지 경우가 있습니다. 그러나 소유권이 올해의 마지막 몇 달 동안 변하고 있으므로 소유권이 이동하면 많은 중복을 초래할 수 있습니다. 나는 현재 가장 먼 곳에서 주인을 데리고 있고, 그 86 명의 다른 사람들을 덮어 쓰고 있습니다.

도움 주셔서 감사합니다.

답변

1

@ Frank의 대답은 훌륭하고 그가 말했듯이 data.table은 롤링 참여가 있지만 dplyr은 그렇지 않습니다. 그래서 data.table이 더 나은 선택이라고 생각합니다. 그러나, dplyr에 머물고 싶다면. 여기 하나의 아이디어가 있습니다.

library(dplyr) 
df3 <- df %>% 
    full_join(df2, by = c("e" = "o")) %>% 
    mutate(Date_ABS_Diff = abs(d - d2)) %>% 
    arrange(e, Date_ABS_Diff) %>% 
    group_by(e) %>% 
    slice(1) %>% 
    select(o = e, d2, a, newowner = p) 
df3 
# A tibble: 4 x 4 
# Groups: o [4] 
       o   d2  a newowner 
      <chr>  <date> <dbl> <chr> 
1 [email protected] 2017-02-02 600.50  Jeff 
2 [email protected] 2017-04-28 3000.00  Sam 
3 [email protected] 2017-05-05 4999.99  <NA> 
4 [email protected] 2017-07-01 2050.60  Jeff 

이 방법은 이메일로 모든 가능한 조합을 결합 full_join를 사용합니다. 그런 다음 날짜 간의 절대 차이를 계산하고 최소 절대 날짜가있는 레코드를 선택하려면 arrangeslice을 사용하십시오.

+0

Nice - 내 마음이 자연스럽게가는 곳이라고 생각합니다. 조인을 롤링하는 방법에 대해 더 자세히 알아야합니다. 슬라이스는 정상적으로 무엇을합니까? 나는 오름차순으로 정렬 한 후 첫 번째 것을 잡을 필터 (! duplicated (e))로 슬라이스를 바꿨을 것이다. Date_ABS_Diff –

+0

@MattW. slice는 위치별로 행을 선택합니다. 다음 문서를 참조하십시오. https://www.rdocumentation.org/packages/dplyr/versions/0.7.3/topics/slice – www

+0

아, 완벽합니다. 매우 감사합니다!새로운 것을 배웠습니다. –

4

이 표준 롤링 업데이트입니다은 data.table에 참여 :

제목 당, 당신은 가장 가까운 일치를 원하는 경우
library(data.table) 
DT = data.table(df) 
DT2 = data.table(df2) 
DT2[DT, on=.(o = e, d2 = d), roll=-Inf, v := i.p ] 

       o   d2  a v 
1: [email protected] 2017-02-02 600.50 Jeff 
2: [email protected] 2017-04-28 3000.00 Sam 
3: [email protected] 2017-05-05 4999.99 NA 
4: [email protected] 2017-07-01 2050.60 Jeff 

대신 roll = -Infroll = "nearest" 사용합니다.

Dplyr에는 롤링 조인이 없으므로 업데이트 조인이 없으므로 아날로그가 없습니다.

+1

대단히 감사합니다. 프랭크! 나는 과거에 data.table을 사용하여 롤링 조인에 대해 배우는 것을 기억하지만, 배울 것이 더 쉬웠 기 때문에 나는 dplyr쪽으로 끌렸다. 이것을 구현하고 어떻게 진행되는지 알려 드리겠습니다. - 빠른 질문 : -Inf가 가장 가까운 전화입니까? 또는 그것은 한쪽에서 가장 가까운 것을 찾거나, 더 일찍 또는 나중에 찾습니까? –

+0

다른 요청이 하나 있습니다. 내가 이것들을 볼 때, 나는 가장 가까운 데이트를하고 싶다. 이것은 현재까지의 거리의 절대 값을 의미한다. 과거 또는 미래의 날짜 일 수 있습니다. 그와 일치하도록 롤 인수를 어떻게 조정합니까? –

+0

@MattW'? data.table'에는'roll ='인수의 값이 문서화되어 있습니다. 나는'roll = "nearest"가 당신이 한 일을 할 것이라고 생각합니다. – Frank

관련 문제