이 문서는 <비즈니스 데이터 분석:R>의 예제를 실습한 내용이다.
현상 : ‘퍼즐’ 게임 앱의 이번 달 매출이 감소하였다. 현상 : 이번 달에 광고집행 예산이 지난 달보다 적었다. 가설 : 광고 축소로 신규유저 매출이 감소했을 것이다.
신규유저 감소를 알아보기 위한 지표 - 신규 가입자 수 (install) - 신규가입 후 접속자 수 (dau/mau) - 신규가입자 중 paid-user - 신규가입자에게서 발생한 매출액
library(data.table)
library(dplyr)
library(ggplot2)
library(scales)
library(pander)
path="/Users/jessymin/Desktop/BizDataAnalysis/R"
dau <- fread(file.path(path, "section3-dau.csv"))
dpu <- fread(file.path(path, "section3-dpu.csv"))
install <- fread(file.path(path, "section3-install.csv"))
dau와 dpu 테이블이 day 단위로 unique user 처리된 것인지 여부를 먼저 확인한다.
dau.check=dau %>%
group_by(log_date) %>%
summarise(user=n(),
uniq.user=length(unique(user_id))
)
dau.check <- mutate(dau.check, compare=user != uniq.user)
sum(dau.check$compare)
## [1] 0
unique user로 처리된 데이터이다. dpu 테이블에 대해서도 동일하게 확인해본다.
dpu.check <- dpu %>%
group_by(log_date) %>%
summarise(user=n(),
uniq.user=length(unique(user_id))
)
dpu.check <- mutate(dpu.check, compare=user != uniq.user)
sum(dpu.check$compare)
## [1] 56
dpu 테이블은 결제 건별로 저장되어 있어, user_id가 중복된다.
dau <- dau %>%
select(-app_name) %>%
mutate(log_month=substr(log_date, 6, 7))
dpu <- dpu %>%
select(-app_name) %>%
mutate(log_month=substr(log_date, 6, 7))
dpu2 <- dpu %>%
group_by(log_date, user_id) %>%
summarise(pay_sum=sum(payment), pay_freq=n())
install <- install %>%
select(-app_name) %>%
mutate(install_month=substr(install_date, 6, 7))
# Merge Data
dau_total <- dau %>%
inner_join(install) %>%
left_join(dpu2)
# Transfer NA
dau_total$pay_sum[is.na(dau_total$pay_sum)] <- 0
dau_total$pay_freq[is.na(dau_total$pay_freq)] <- 0
# Categorize paid/non-paid user
dau_total <- mutate(dau_total, paid_user="paid")
dau_total$paid_user[dau_total$pay_sum == 0] <- "non-paid"
# Categorize new/existing user
dau_total$new_user <- ifelse(dau_total$install_month == dau_total$log_month, "newby", "existing")
# Factorizing variables
dau_total$new_user <- factor(dau_total$new_user, c("newby", "existing"))
dau_total$install_month <- factor(dau_total$install_month, c("07","06","05","04"))
일반적인 지표는 다음과 같다.
summary1 <- dau_total %>%
group_by(log_month) %>%
summarise(MAU=length(unique(user_id)))
summary1 <- summary1 %>% inner_join(
filter(dau_total, paid_user == "paid") %>%
group_by(log_month) %>%
summarise(MPU=length(unique(user_id)),
Revenue=sum(pay_sum)
)
)
summary1 <- mutate(summary1, ARPU=round(Revenue/MAU)) %>%
mutate(ARPPU=round(Revenue/MPU))
pander(comma(summary1))
| log_month | MAU | MPU | Revenue | ARPU | ARPPU |
|---|---|---|---|---|---|
| 06 | 14,807 | 124 | 2,277,230 | 154 | 18,365 |
| 07 | 12,229 | 115 | 2,070,850 | 169 | 18,007 |
매출이 감소했으나, MAU의 감소로 ARPU는 소폭 상승했다. ARPU : Average Revenue per User ARPPU : Average Revenue per Paid User
다음으로 6월/7월 신규 가입자에 관한 지표를 상세히 살펴본다.
summary2 <- install %>%
filter(install_month %in% c("06", "07")) %>%
group_by(install_month) %>%
summarise(total_user=length(user_id))
summary2 <- cbind(summary2,
(dau_total %>%
filter(new_user == "newby" & paid_user == "paid") %>%
group_by(log_month) %>%
summarise(paid_user=length(unique(user_id)),
Revenue=sum(pay_sum)) %>%
select(-log_month)
)
)
summary2 <- summary2 %>%
mutate(ARPU=round(Revenue/total_user),
ARPPU=round(Revenue/paid_user))
pander(comma(summary2))
| install_month | total_user | paid_user | Revenue | ARPU | ARPPU |
|---|---|---|---|---|---|
| 06 | 9,209 | 48 | 498,370 | 54 | 10,383 |
| 07 | 6,631 | 39 | 291,990 | 44 | 7,487 |
7월 신규가입자 수는 6월보다 감소했으며, 이에 따라 과금한 유저 및 발생 매출액도 감소했다.
pal4 <- c("#08519c","#737373","#969696","#bdbdbd")
pal2 <- c("#0570b0", "#737373")
install_df <- install %>% group_by(install_month) %>%
summarise(count=n())
ggplot(install_df, aes(install_month, count)) +
geom_bar(stat="identity", fill="steelblue", width=0.4) +
geom_text(aes(label=comma(count)), vjust=-0.2, size=3.5) +
scale_y_continuous(labels=comma) +
ggtitle("New Registered User")
7월에 신규가입한 유저 수는 6월 대비 약 28%(2,578명) 감소했다.
신규유저 획득에 문제가 발생했다.
먼저 7월에 전월 대비 활성화 유저가 얼마나 줄었는지 파악해 본다.
mau <- dau_total %>% group_by(log_month) %>%
summarise(count=length(unique(user_id)))
ggplot(mau, aes(log_month, count)) +
geom_bar(stat="identity", fill="steelblue", width=0.4) +
geom_text(aes(label=comma(count)),
vjust=-0.3, size=3.5) +
scale_y_continuous(labels=comma) +
ggtitle("MAU")
7월 활성화 유저는 전월 대비 2,578명 감소했다. 가입자 수 감소량과 같다. 가입월별로 자세히 살펴본다.
mau.install_month <- dau_total %>%
group_by(log_month, install_month) %>%
summarise(count=length(unique(user_id)))
ggplot(mau.install_month, aes(log_month, count, fill=install_month)) +
geom_bar(stat="identity", width=0.4) +
geom_text(aes(label=comma(count)),
size=3.5,
position=position_stack(vjust=0.5)) +
scale_y_continuous(labels=comma) +
scale_fill_manual(values=pal4) +
ggtitle("MAU by Registered Month")
mau.new_user <- dau_total %>%
group_by(log_month, new_user) %>%
summarise(count=length(unique(user_id)))
ggplot(mau.new_user, aes(log_month, count, fill=new_user)) +
geom_bar(stat="identity", width=0.4) +
geom_text(aes(label=comma(count)),
size=3.5,
position=position_stack(vjust=0.5)) +
scale_y_continuous(labels=comma) +
scale_fill_manual(values=pal2) +
ggtitle("MAU by User Type")
mpu <- dau_total %>%
filter(paid_user == "paid") %>%
group_by(log_month, install_month) %>%
summarise(count=length(unique(user_id)))
ggplot(mpu, aes(log_month, count, fill=install_month)) +
geom_bar(stat="identity", width=0.4) +
geom_text(aes(label=comma(count)),
position=position_stack(vjust=0.5),
size=3.5) +
scale_fill_manual(values=pal4) +
ggtitle("Paid-user by Install month")
mpu.new_user <- dau_total %>% filter(paid_user == "paid") %>%
group_by(log_month, new_user) %>%
summarise(count=length(unique(user_id)))
ggplot(mpu.new_user, aes(log_month, count, fill=new_user)) +
geom_bar(stat="identity", width=0.4) +
geom_text(aes(label=comma(count)),
size=3.5,
position=position_stack(vjust=0.5)) +
scale_fill_manual(values=pal2) +
ggtitle("Paid-user by User Type")
기존 유저의 수가 6월/7월 동일하다. 앞서와 마찬가지로, 책의 예제로 사용하기 위해 데이터 추출 후 일부 필터링한 것을 알 수 있다.
df <- dau_total %>%
group_by(log_month, install_month) %>%
summarise(total_payment=sum(pay_sum))
ggplot(df, aes(log_month, total_payment, fill=install_month)) +
geom_bar(stat="identity", width=0.4) +
geom_text(aes(label=comma(total_payment)),
position=position_stack(vjust=0.5),
size=3.5) +
scale_y_continuous(labels=comma) +
scale_fill_manual(values=pal4) +
ggtitle("Revenue per Registered Month")
df <- dau_total %>% group_by(log_month, new_user) %>%
summarise(total_payment=sum(pay_sum))
ggplot(df, aes(log_month, total_payment, fill=new_user)) +
geom_bar(stat="identity", width=0.4) +
geom_text(aes(label=comma(total_payment)),
position=position_stack(vjust=0.5),
size=3.5) +
scale_y_continuous(labels=comma) +
scale_fill_manual(values=pal2) +
ggtitle("Revenue per User Type")
기존 유저로부터 발생한 매출액 역시 동일하게 셋팅되어 있다. 의도적으로 셋팅한 것이 확실하다.
따라서 더 이상의 디테일한 분석은 하지 않고 실습을 여기서 마무리하기로 한다.