日本認知心理学会 研究法研究部会 第8回研究会(2026.03.14)

「ベータ分布を用いた割合・確率データのモデリング」サンプルコード


#パッケージ読み込み

library(brms)

library(tidyverse)

library(palmerpenguins)



#ベータ分布の描画

x <- seq(0.001, 0.999, length=1000)


par1 <- data.frame(mu=c(0.1, 0.25, 0.5, 0.75, 0.9),

                  phi=c(10, 10, 10, 10, 10))


df1 <- do.call(rbind, lapply(1:nrow(par1), function(i){

  mu <- par1$mu[i]

  phi <- par1$phi[i]

  alpha <- mu*phi

  beta <- (1-mu)*phi

  

  data.frame(x=x,

             density=dbeta(x, alpha, beta),

             mu=mu,

             phi=phi)

}))


ggplot(df1, aes(x, density, color=factor(mu))) +

  geom_line(linewidth=1) +

  labs(x=NULL, color="mu")



par2 <- data.frame(mu=c(0.5, 0.5, 0.5),

                   phi=c(5, 10, 50))


df2 <- do.call(rbind, lapply(1:nrow(par2), function(i){

  mu <- par2$mu[i]

  phi <- par2$phi[i]

  alpha <- mu*phi

  beta <- (1-mu)*phi

  

  data.frame(x=x,

             density=dbeta(x, alpha, beta),

             mu=mu,

             phi=phi)

}))


ggplot(df2, aes(x, density, color=factor(phi))) +

  geom_line(linewidth=1) +

  labs(x=NULL, color="phi")



#brmsによるベータ回帰

#palmerpenguinsパッケージのpenguinデータを使用

pen <- na.omit(penguins)


#くちばしの長さに対する太さの割合(bill_ratio)変数を作成

pen$bill_ratio <- pen$bill_depth_mm/pen$bill_length_mm


#くちばしの太さの割合を種ごとに比較

model1 <- brm(bill_ratio ~ species,

  data = pen,

  family = Beta(),

  chains = 4,

  iter = 1000,

  seed = 0314)


summary(model1)

plogis(-0.10) #Adelieの平均μ

plogis(-0.10-0.39) #Chinstrapの平均μ

plogis(-0.10-0.67) #Gentooの平均μ


model1_est <- conditional_effects(model1, effects="species")

model1_est

model1_est$species


#種間の差の事後分布を図示

nd <- data.frame(species = levels(pen$species))

mu_post <- posterior_epred(model1, newdata = nd)

mu_diff <- data.frame(Chinstrap_vs_Adelie = mu_post[,2] - mu_post[,1],

                      Gentoo_vs_Adelie = mu_post[,3] - mu_post[,1])


mu_diff |>

  pivot_longer(everything()) |>

  ggplot(aes(x = value)) +

  geom_density(fill="skyblue", alpha=.5) +

  facet_wrap(~name) +

  geom_vline(xintercept = 0, linetype="dashed") +

  labs(x = "Difference in μ", y = "Posterior density")


#μをオッズ比に変換して図示

mu_logit <- posterior_linpred(model1, newdata = nd)

OR <- data.frame(Chinstrap_vs_Adelie = exp(mu_logit[,2] - mu_logit[,1]),

                 Gentoo_vs_Adelie = exp(mu_logit[,3] - mu_logit[,1]))

OR |>

  pivot_longer(everything()) |>

  ggplot(aes(x = value)) +

  geom_density(fill="orange", alpha=.5) +

  facet_wrap(~name) +

  geom_vline(xintercept = 1, linetype="dashed") +

  labs(x = "odds rate", y = "Posterior density")

#使わないか...


#くちばしの太さの割合を翼の長さで予測

pen$flipper_length_z <- scale(pen$flipper_length_mm)


model2 <- brm(bill_ratio ~ flipper_length_z,

  data = pen,

  family = Beta(),

  chains = 4,

  iter = 1000,

  seed = 0314)


summary(model2)


model2_est <- conditional_effects(model2)

model2_est