2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

勝手に添削:Tokyo.Rの新規率・直帰率について集計・プロットしてみた #rstatsj

Posted at

呼ばれた気がしたので添削してみる。

1. イベントIDの取得

R
library(dplyr)
library(rvest)
library(stringr)

url <- iconv("http://api.atnd.org/events/?keyword=R勉強会@東京&count=100", "sjis", "utf8")

doc <- html(url)

event_id <- doc %>% 
  html_nodes(xpath = "//events/event/event_id") %>% 
  html_text %>% 
  as.integer
title <- doc %>% 
  html_nodes(xpath = "//events/event/title") %>% 
  html_text

events <- data.frame(event_id, title) %>% 
  filter(str_detect(title, "^第[[:digit:]]+回R勉強会@東京")) %>%
  arrange(desc(event_id)) %>%
  mutate(time = rev(row_number())) %>%
  select(event_id, time)

head(events)
結果
  event_id time
1    68150   49
2    66469   48
3    63990   47
4    61553   46
5    60908   45
6    57640   44

Windows だからか、URL は UTF-8 に変換してやらないとうまくいかなかった。

ポイントは 2 つ。

  • "第[0-9|0-9]+回" という正規表現の書き方は、第[[:digit:]]+回 みたいな書き方があります。この書き方については R における正規表現 - RjpWiki が詳しいです。
  • time = seq(dim(.)[1], 1, -1) のところは time = rev(row_number()) と書けます。row_number()dplyr の便利関数です。

2. 出席者の取得

指定したイベントIDの出席者を取得する関数を作成し、各回の出席者を取得する。 @hoxo_m氏のpforeachパッケージでもっと楽にできそうな気もする。

ということなので、pforeach で書いてみる。

R
library(pforeach)

get_users <- function(event_id, time) {
  cat(time, event_id, "\n")
  url <- sprintf("http://api.atnd.org/events/users/?event_id=%s", event_id)
  doc <- html(url)
  Sys.sleep(1)
  get_node_text <- function(node_name) {
    xpath <- sprintf("//events/event/users/user/%s", node_name)
    doc %>% html_nodes(xpath = xpath) %>% html_text
  }
  data_frame(event_id = event_id, 
             time = time, 
             user_id = get_node_text("user_id"),
             nickname = get_node_text("nickname"),
             twitter_id = get_node_text("twitter_id"),
             status = get_node_text("status"))
}

npforeach(row=rows(events), .c=rbind)({
  get_users(row$event_id, row$time)
}) -> users

head(users)
結果
  event_id time user_id       nickname     twitter_id status
1    68150   49  145711 __john_smith__ __john_smith__      1
2    68150   49  159246         缶これ    wonder_zone      1
3    68150   49   21686       kos59125       kos59125      1
4    68150   49  109170   tom_of_death   tom_of_death      1
5    68150   49  173679         re_t_s         re_t_s      1
6    68150   49  166177   YugoKawamura                     1

特に楽にはならないっす。

好みの問題だけど、私ならこういうときは lambdaR を使います。

R
library(lambdaR)

users <- events %>% 
  Map2_(get_users) %>%
  rbind_all

3. 前回出席回、次回出席回、直帰フラグの追加

ここからちょっと元記事とは違う定義にします。

  • 新規参加:初めての参加
  • 離脱:その回が最後の参加
  • 直帰:初めての参加かつ、その回が最後

好みの問題かもしれませんが、この定義の方がしっくりくる。
なので、ここで追加する列もシンプルになります。

R
users2 <- users %>% 
  group_by(user_id) %>% 
  arrange(time) %>% 
  mutate(first = first(time) == time, 
         last = last(time) == time, 
         bounce = first & last)

head(users2)
結果
  event_id time user_id         nickname   twitter_id status first  last bounce
1     5441    6   10046          rti7743    super_rti      1  TRUE FALSE  FALSE
2     6439    7   10046          rti7743    super_rti      1 FALSE FALSE  FALSE
3     9177   10   10046          rti7743    super_rti      1 FALSE FALSE  FALSE
4    14967   13   10046          rti7743    super_rti      1 FALSE  TRUE  FALSE
5    28416   23  100744         天才白菜        bae_j      1  TRUE  TRUE   TRUE
6    24629   20  100799 Akihiro Kasahara Aki_Kasahara      1  TRUE FALSE  FALSE

4. 新規率、離脱率、直帰率の算出

R
result <- users2 %>% 
  group_by(time) %>%
  summarise(n = n(), 
            new = sum(first),
            exit = sum(last),
            bounce = sum(bounce),
            new_rate = new / n,
            exit_rate = exit / n,
            bounce_rate = bounce / new) %>%
  arrange(desc(time))

head(result)
結果
  time   n new exit bounce  new_rate exit_rate bounce_rate
1   49 113  31  113     31 0.2743363 1.0000000   1.0000000
2   48  97  36   60     30 0.3711340 0.6185567   0.8333333
3   47  84  38   44     34 0.4523810 0.5238095   0.8947368
4   46 138  56   69     42 0.4057971 0.5000000   0.7500000
5   45  90  29   35     17 0.3222222 0.3888889   0.5862069
6   44  99  32   47     27 0.3232323 0.4747475   0.8437500

一つポイントなのは、summarise(とmutate)は左で求めた値を右側で使い回すことができるということです。(transform では無理)
なので n とかは使い回したほうが再計算されなくて地球にやさしい。

R
library(ggvis)

data <- result %>% slice(1:20)
result %>% ggvis(~ time, ~ bounce_rate) %>% layer_paths

bounce_rate.png

R
result %>% ggvis(~ time, ~ new_rate) %>% layer_paths

new_rate.png

プロットしてみると、定義は違うけど、ほとんど同じ動きをしています。
おもしろいなー。

Enjoy!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?