R을 이용한 고객 이탈 판정 따라하기

R을 이용한 고객 이탈 판정 따라하기

Summary:

Curycu님의 ‘고객 구매주기 및 서비스 이탈 고객 판정’ 포스팅을 읽고 실습했습니다.


이탈 고객 판정

이커머스에서의 이탈 고객 판정은 어렵다. 고객마다 구매 주기가 다름은 물론, 구매 간격이 긴 것이 이탈일 수도, 그 고객만의 사이클일수도 있기 때문이다. 식품, 전자제품 등 제품마다 구매 간격이 다른 것도 고객 이탈 판정을 까다롭게 만든다.

R을 이용하면 애매한 고객의 서비스 이탈 여부를 체계적으로 판정할 수 있다. Curycu님께서 이탈 고객 판정 로직을 만들어 공개했는데 오늘은 Curycu님의 사고 과정을 따라가보려고 한다.


기본 세팅


R 구현 과정(전체 코드)

1. 패키지 설치 및 불러오기

# 패키지 설치 여부 확인
installed.packages("dplyr")
installed.packages("data.table")
installed.packages("ggplot2")
installed.packages("scales")

# 패키지 설치
install.packages("dplyr")
install.packages("data.table")
install.packages("ggplot2")
install.packages("scales")

# 패키지 불러오기
library(dplyr)
library(data.table)
library(ggplot2)
library(scales)

dplyr, data.table, ggplot2, scales 패키지가 필요하다. 자신의 환경에 이 패키지들이 설치되었는지 확인하고 설치되지 않았다면 install.packages("패키지명") 코드를 실행하여 패키지를 설치한다.

2. 변수 정의

rdate <- function(n=1, from=Sys.Date()-365*1, to=Sys.Date()){
  interval <- difftime(round(to), round(from))
  rday <- rbeta(n, 1, 3) * interval
  from + floor(rday)
}

rstr <- function(n=1, str.len=2) {
  rn <- runif(str.len * n, 1, 24)
  df <- as.data.frame(matrix(rn, str.len, n))
  num.to.str <- function(v) paste0(LETTERS[v], collapse='')
  res <- sapply(df, num.to.str)
  names(res) <- NULL
  res
}

함수를 직접 만들 때 ‘function(){ }’을 사용한다. 여기서는 rdate, rstr이라는 변수에 각각 함수를 정의했다. rdate에는 ‘n=1, from=작년 오늘 날짜, to=오늘 날짜’ 3가지를, rstr에는 ‘n=1, str.len=2’ 2가지를 입력값으로 쓴다.

diff.custom <-
  function(v, fun=`-`) {
    if(length(v) < 2){
      as.numeric(c())
    }else{
      after <- v[2:length(v)]
      before <- v[1:(length(v)-1)]
      fun(after, before)
    }
  }

diff.week <-
  function(to, from) floor(difftime(to, from, units = 'weeks'))
purchase.history <-
  data.frame(
    user.id = rstr(10^5,4),
    purchase.date = rdate(10^5)) %>%
  distinct %>%
  arrange(user.id, purchase.date) %>%
  mutate(p.date = as.Date(purchase.date))
purchase.diff <-
  purchase.history %>%
  group_by(user.id) %>%
  mutate(week.gap = c(0, diff.custom(p.date, diff.week)))

purchase.diff.max <-
  purchase.diff %>%
  group_by(user.id) %>%
  summarise(max.week.gap = max(week.gap))
purchase.pivot.week <-
  purchase.diff.max %>%
  group_by(max.week.gap) %>%
  summarise(user.count = n())
purchase.pivot.week %>%
  ggplot(aes(x=max.week.gap, y=user.count)) +
  geom_line() +
  geom_text(aes(y=user.count, label = max.week.gap)) +
  scale_y_continuous(label = comma)

purchase.pivot.week %>%
  filter(max.week.gap > 0) %>%
  ggplot(aes(x=max.week.gap, y=user.count)) +
  geom_line() +
  geom_text(aes(y=user.count, label = max.week.gap)) +
  scale_y_continuous(label = comma)
total.user <- purchase.pivot.week %>% summarise(sum(user.count)) %>% .[[1]]

purchase.week.ratio <-
  purchase.pivot.week %>%
  mutate(cumsum.user = cumsum(user.count)) %>%
  mutate(wrong.classification.ratio = round((total.user - cumsum.user) / total.user, 2))
View(purchase.week.ratio)

Hyeyeon

A Blog about E-Commerce and Product Management

comments powered by Disqus

    rss facebook twitter github youtube mail spotify instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora