LoginSignup
44

More than 3 years have passed since last update.

『効果検証入門』のすごいところベスト5

Posted at

安井翔太著『効果検証入門』を読了しました。

因果推論や統計の基礎を学ぶ上でとても良い本でしたが、同時に作者のRコードもかなり洗練されていてRの勉強にもなりました。そこで今回は書籍で紹介されているコードの中からとくにエレガントだと思った箇所を5か所ピックアップしました。

コード全文はここにあります

第5位:エラーバーのプロット

ggplot2でエラーバーをプロットするのは地味に面倒だが、お手本のようなコードなので、このままコピペして使える

using_voucher_results %>%
  ggplot(aes(y = estimate, x = model_index)) +
  geom_point() +
  geom_errorbar(aes(ymax = estimate + std.error*1.96,
                    ymin = estimate - std.error*1.96,
                    width = 0.1)) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        plot.title = element_text(hjust = 0.5),
        legend.position = "bottom",
        plot.margin = margin(0.5,1,0.5,1, "cm"))

第4位:回帰分析への神パイプライン

data → 回帰モデル → broom:tidy() という華麗なるパス

ong_coef <- biased_data %>%
  lm(data = .,
     formula = spend ~ treatment + recency + channel + history) %>%
  tidy()

summary ではなく tidy() を使うことで結果をデータフレーム化することができ、パラメータの取り出しが容易になる

## aの結果から介入効果に関するパラメーターのみを取り出す
alpha_1 <- short_coef %>%
  filter(term == "treatment") %>%
  pull(estimate)

第3位: pull の利用

pull関数はデータフレームの特定のカラムをベクトルとして取り出す関数

selectと似ているが、pullの場合はベクトルなので検定モデルに入れやすい

# (6) t検定を行う
## (a)男性向けメールが配信されたグループの購買データを得る
mens_mail <- male_df %>%
  filter(treatment == 1) %>%
  pull(spend)

## (b)メールが配信されなかったグループの購買データを得る
no_mail <- male_df %>%
  filter(treatment == 0) %>%
  pull(spend)

## (a)(b)の平均の差に対して有意差検定を実行する
rct_ttest <- t.test(mens_mail, no_mail, var.equal = T)

第2位:回帰分析の自動化

複数のモデルをbroomパッケージを使って効率的に回す

## モデル式のベクトルを用意
formula_vec <- c(spend ~ treatment + recency + channel, # モデルA
               spend ~ treatment + recency + channel + history, # モデルB
               history ~ treatment + channel + recency) # モデルC

## formulaに名前を付ける
names(formula_vec) <- paste("reg", LETTERS[1:3], sep ="_")

## モデル式のデータフレーム化
models = formula_vec %>%
  enframe(name = "model_index", value = "formula")

## まとめて回帰分析を実行
df_models <- models %>%
  mutate(model = map(.x = formula, .f = lm, data = biased_data)) %>%
  mutate(lm_result = map(.x = model, .f = tidy))

enframe 関数が良い味出してます

第1位:バイアスのあるデータの作成

こんな方法があるなんて…

obs_rate_c <- 0.5
obs_rate_t <- 0.5
## バイアスのあるデータを作成
biased_data <- male_df %>%
  mutate(obs_rate_c =
           ifelse( (history > 300) | (recency < 6) |
                     (channel == "Multichannel"), obs_rate_c, 1),
         obs_rate_t =
           ifelse( (history > 300) | (recency < 6) |
                     (channel == "Multichannel"), 1, obs_rate_t),
         random_number = runif(n = NROW(male_df))) %>%
  filter( (treatment == 0 & random_number < obs_rate_c ) |
            (treatment == 1 & random_number < obs_rate_t) )

サンプルの値に基づいて、閾値をルールベースで決める→一様乱数をmutateで作成→閾値とrandom_number を比べてfilteringという方法

どうやって思いつくんだろう

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
44