2017-12-18 12 views
1

데이터 프레임 내의 그룹으로 특정 패턴을 찾으려고합니다. 이메일, 주문을 한 사람 및 금액을 기준으로 다음과 같은 주문 데이터 프레임을 가져옵니다.dplyr의 시계열 그룹화 및 필터링

set.seed(123) 
dates = sample(seq(as.Date("2017-01-01"),as.Date("2017-12-31"), by = 'day'), 2000, replace = TRUE) 
amount <- sample(-50:100, 2000, replace = TRUE) 
placedorder <- sample(c(NA, NA, NA, "jeff", "alex", "steve", "amy", "john", "larry", "ryan"), 2000, replace = TRUE) 
email <- sample(paste0(1:200, "@gmail.com"), 2000, replace = TRUE) 
df <- data.frame(dates, email, placedorder, amount, stringsAsFactors = FALSE) 
나는 그들이 날짜 연속적으로 발생하는 이메일이 모든 세 가지가 발생 주소, 에 의해 그룹 찾고 싶은

:

  1. 명령서

    긍정적로 배치되었다 값이고 placedorder이 NA 인 경우
  2. 음수가 인 wh 위의 단계와 wh 감수 placedorder는 순서가 긍정적 값을, 단계 2 이후에 배치되었다
  3. 를 NA placeholder하지

예 NA이다 :

# A tibble: 10 x 4 
# Groups: email [1] 
     dates  email placedorder amount 
     <date>  <chr>  <chr> <int> 
1 2017-02-10 [email protected]  <NA>  68 # satisfies #1 
2 2017-02-27 [email protected]  <NA> -21 # satisfies #2 
3 2017-03-07 [email protected]  jeff  -9 
4 2017-03-09 [email protected]  steve -93 
5 2017-03-14 [email protected]  steve  22 # satisfies #3 
6 2017-03-18 [email protected]  steve -81 
7 2017-04-28 [email protected]  <NA> -12 
8 2017-05-06 [email protected]  <NA>  4 
9 2017-06-03 [email protected]  jeff -40 
10 2017-06-03 [email protected]  larry  13 #(this also satisfies #3) 

상기 예 모두 email 내에 있으며, 3 개의 필터 각각은 시간에 대해 차례대로 발생합니다.

제 생각에는 이러한 시도가 어디에서 발생했는지는 알지만 날짜와 이러한 문제가 연속해서 발생하지는 않습니다. 또한 실제로 이러한 순서로 필터링하면 가장 좋을 것입니다.

df2 <- df %>% 
    group_by(email) %>% 
    filter(any(is.na(placedorder) & amount > 0), 
     any(is.na(placedorder) & amount < 0), 
     any(!is.na(placedorder) & amount > 0) 
) 

미리 감사드립니다. "첫 번째 순서"와 "두 번째 순서"의 나의 해석을 가정

+0

몇 가지 질문이 있습니다. "후"또는 데이터 세트 행 번호와 마찬가지로 말할 때 시간 상 승계에 대해 이야기하고 있습니까? 일시적인 경우 날짜와 전자 메일에 대한 데이터 집합을 먼저 정렬합니다 (계산 시간에 저장하도록 전자 메일 정렬). 둘째, 세 가지 조건이 동시에 충족되도록 필터링하고 싶습니까? 또한 문제가 POSIXct 인 날짜에서 발생하는 경우 필요에 따라 다시 문자로 변환하고 나중에 다시 디버깅하기 쉽습니다 (주석이있는 경우). – Arani

+0

나는 처음 사건 발생 후 날짜에 일어난 것처럼 "애프터"를 의미했습니다.모든 세 조건이 주어진 그룹 내에서 동시에 만족되도록 서로 필터링하고 싶습니다. 그리고 서로 후에 발생하는 날짜에 발생합니다 (날짜 사이의 거리가 될 수 있음). –

+0

편집 된 게시물이 예 –

답변

2

여기, 정확 dplyr

library(dplyr) 

df %>% group_by(email) %>% 
    arrange(email, dates) %>% 
    mutate(order_num=1:n()) %>% 
    #An order was placed with a positive value and where placedorder is NA 
    filter((is.na(placedorder) & amount>0) | 
    # An order was placed after the first one, with a negative value and where placedorder is NA 
     (is.na(placedorder) & amount <0 & order_num >1) | 
    # An order was placed after the second order, with a positive value and where placeholder is not NA 
     (!is.na(placedorder) & amount >0 & order_num > 2) 
    ) 

UPDATE의 명령을 설정하는 하나 개의 방법 : 질문을 명확히 주셔서 감사합니다. 기본적으로 "고객 상태보기"를 원하고 이전 유형을 관찰 한 후에 만 ​​다음 유형의 이벤트를 추적하기를 원합니다.

df %>% group_by(email) %>% 
    arrange(email, dates) %>% 
    mutate(event_1=ifelse(is.na(placedorder) & amount>0, 1, 0), 
     post_event_1=cumsum(event_1), 
     # only if at least one event_1 has happened 
     event_2=ifelse(post_event_1>=1 & is.na(placedorder) & amount <0, 1,0), 
     post_event_2=cumsum(event_2), 
     # only if at least one event_2 has happened 
     event_3=ifelse(post_event_2>=1 & !is.na(placedorder) & amount >0, 1, 0)) %>% 
    # only interested in first occurance of event_1 and event_2 preceding event_3 
    filter((event_1==1 & post_event_1==1) | (event_2==1 & post_event_2==1) | event_3 ==1) 

# A tibble: 390 x 9 
# Groups: email [165] 
     dates   email placedorder amount event_1 post_event_1 event_2 post_event_2 event_3 
     <date>   <chr>  <chr> <int> <dbl>  <dbl> <dbl>  <dbl> <dbl> 
1 2017-01-29 [email protected]  <NA>  76  1   1  0   0  0 
2 2017-05-25 [email protected]  <NA> -37  0   1  1   1  0 
3 2017-08-14 [email protected]  steve  53  0   1  0   2  1 
4 2017-12-21 [email protected]  john  92  0   2  0   4  1 
5 2017-02-08 [email protected]  <NA>  89  1   1  0   0  0 
6 2017-01-16 [email protected]  <NA>  40  1   1  0   0  0 
7 2017-03-18 [email protected]  <NA>  20  1   1  0   0  0 
8 2017-05-16 [email protected]  <NA> -45  0   2  1   1  0 
9 2017-06-08 [email protected]  larry  46  0   2  0   2  1 
10 2017-07-22 [email protected]  john  93  0   3  0   2  1 
# ... with 380 more rows 

일부 "되지 않은 체인"이 있습니다 예를 들어, 다음은 이러한 "상태"를 통해 고객 전이를 추적에서 (약간 자세한지만, 희망 이해할 수) 시도이다 고객이 state_1로 진행했을 때 더 이상 진행하지 않았습니다. 당신이 그들을 드롭하려는 경우 확실하지 않습니다 (당신은 전자 메일 당 관측 수를 세 수 미만의 레코드를 삭제할 수 있습니다).

+0

을 표시합니다. 감사합니다. @ dmi3kno. 먼저 이메일로 그룹화해야합니다. 동일한 전자 메일 내에서 발생해야합니다. 그러나 그것의 꼭대기에 나는 "1 차 주문"과 "2 차 주문"을 명확히하지 않았다고 생각합니다. 11 월 1 일에서 20 일 사이에 20 차례의 주문이있을 수 있습니다. 나는 발생 1이 발생하고, 2, 3이 어떤 주어진 날짜에 일어나는 경우를 찾고 싶지만, 날짜는 서로 뒤따라야한다. –

+0

나는 OP가 & 대신에 |를 원하고 그의 코멘트로 판단한다고 생각한다. 우수 답변 BTW. – Arani

+0

그래, 내가하고 싶어하고, _but_ 또한'order_num'는 작동하지 않습니다. 내 게시물에 좀 더 자세하게 설명하는 내용을 더 추가했습니다! –

관련 문제