廿TT

譬如水怙牛過窓櫺 頭角四蹄都過了 因甚麼尾巴過不得

[R+Google アナリティクス]リセンシーどこで切るチャート

今日の川柳

アクセス解析の分野ではユーザーの離脱率や維持率を把握したいというニーズがあります。しかし、離脱するユーザーは単にサイトへの訪問を止めるだけで、わざわざ離脱を申告することはめったにありません。このような場合、例えば 「3ヶ月訪問がなければ離脱したと判断する」などのルールを決めることがあります。この「離脱した」と判断する区切りは、3ヶ月がいいのか、2ヶ月がいいのか、4ヶ月がいいのか、難しいところです。

その判断をサポートするために以下のようなグラフを書いてみてはいかがでしょうか。

  1. データセットを学習期間と評価期間に分ける
  2. 閾値を定める
  3. 学習期間で閾値を超えた日数訪問しなかったユーザーを「離脱」、それ以外を「維持」と判断
  4. 維持と判断されたユーザーが、評価期間に再訪問があったユーザーの内、何パーセントかを数える(active)
  5. 同様、維持と判断されたユーザーが、評価期間に再訪問がなかったユーザーの内、何パーセントかを数える(inactive)
  6. 閾値をいろいろ変えて同じことを繰り返す
  7. 閾値を横軸に、active と inactive を縦軸にとりプロット

f:id:abrahamcow:20180209214723p:plain

この図をみると、たとえば閾値を25日とした場合、維持ユーザーの50%強にリーチできる一方で、離脱ユーザーの25%強を維持ユーザーと判断してしまうことがわかります。

active をリターン、inactive をロスと考えると、目標とするリターンを得るためにはどの程度のロスがあるか、あるいはロスをある水準に抑えたい場合にどの程度のリターンが得られるか、大雑把に把握して閾値を決めることができます。

リターンやロスに特に指針がない場合は、active と inactive の差が最大になる点を閾値とすればよいでしょう。

上の図はGoogle アナリティクスのデータから持ってきたもので、2017-07-01から2017-9-30を学習期間、2017-10-01から2017-12-31を評価期間としています。

図を書いた R のコードを載せます。"dimension1" にはユーザーidが入るように設定しています。

library(googleAnalyticsR)
library(tidyverse)
#####
ga_auth()
account_list <- ga_account_list()
ga_id <- account_list$viewId[3]

gadata <-
  google_analytics_4(ga_id,
                     date_range = c("2017-07-01","2017-12-31"),
                     metrics = c("sessions"),
                     filtersExpression = "ga:userType==Returning Visitor",
                     dimensions = c("date","dimension1","channelGrouping"),
                     max = 15000)
gadata_a <- dplyr::filter(gadata,date<=as.Date("2017-9-30"))
gadata_b <- dplyr::filter(gadata,date>as.Date("2017-9-30"))

uid_b <-unique(gadata_b$dimension1)

lastdate <-gadata_a %>% 
  group_by(dimension1) %>% 
  summarise(date=date[which.max(date)],channelGrouping=channelGrouping[which.max(date)])

seq_d <-seq.Date(as.Date("2017-07-01"),as.Date("2017-09-30"),by="1 day")

dflast <-data_frame(date=seq_d) %>% 
  left_join(lastdate,by = "date") %>% 
  mutate(Recency=as.integer(as.Date("2017-09-30")-date))

dfR <- dflast %>% 
  group_by(Recency) %>% 
  summarise(active=sum(dimension1 %in% uid_b),
            inactive=sum(!(dimension1 %in% uid_b))) 


pR<-ggplot(dfR,aes(x=Recency))+
  geom_step(aes(y=cumsum(active)/sum(active),colour="active"),size=1)+
  geom_step(aes(y=cumsum(inactive)/sum(inactive),colour="inactive"),size=1)+
  theme_gray(18)+
  theme(legend.title = element_blank())+
  ylab("")+
  scale_y_continuous(labels = scales::percent)
print(pR)

#ggsave("~/Desktop/pR.png",pR)

ユーザーを層別したい場合は以下のようにするとよいでしょう。

下図は直近訪問時のチャネルごとにユーザーを分けて active と inactive をプロットしたものです。

f:id:abrahamcow:20180209221322p:plain

dfR2 <- dflast%>%
  dplyr::filter(channelGrouping != "(Other)") %>% 
  group_by(Recency,channelGrouping) %>% 
  summarise(active_n=sum(dimension1 %in% uid_b),
            inactive_n=sum(!(dimension1 %in% uid_b))) %>%
  group_by(channelGrouping) %>% 
  arrange(Recency) %>% 
  mutate(active=cumsum(active_n)/sum(active_n),
         inactive=cumsum(inactive_n)/sum(inactive_n)) %>% 
  gather(state,proportion,-Recency,-channelGrouping,-active_n,-inactive_n)

pR2<-ggplot(dfR2,aes(x=Recency))+
  geom_step(aes(y=proportion,colour=state),size=1)+
  facet_wrap(~channelGrouping)+
  theme_gray(18)+
  theme(legend.title = element_blank())+
  ylab("")+
  scale_y_continuous(labels = scales::percent)
print(pR2)

#ggsave("~/Desktop/pR2.png",pR2)