【R】glhtとemmeansのcld( )は異なる仕様

R

Rで多重比較を行いcompact letter display(CLD)を付与すると、glht()emmeans()文字の付き方が異なることがあります。

Attention Required! | Cloudflare

どちらもTukeyの多重比較を行っているはずなのに、

  • glht では「直感に反する文字配置」になる
  • emmeans では「平均値順のCLD」になる

という経験をした方も多いのではないでしょうか。

本記事では、この違いが偶然やバグではなく、仕様として説明できることを、公式ドキュメントおよびインターネット上の情報をもとに整理します。

CLD 生成フローの違い

glht()emmeans()は、ともにPiepho (2004) のアルゴリズムを用いてCLD を生成します。

ただし、CLDを作成するときに呼び出される関数cld()は、同じ名前でも実体が異なる関数です。

手法CLDの付与順
multcomp::cld()因子レベル順
emmeans::cld()推定平均値順

multcomp::cld()の仕様

multcomp::cld()は、glhtオブジェクトに対するS3メソッドとして定義されています。

cld(object, level = 0.05, decreasing = FALSE, ...)

ここで重要なのは、

  • decreasing は 文字(a, b, c …)の昇順・降順を切り替えるだけ
  • 因子レベルの並び替えや平均値によるソート機能は存在しない

という点です。

つまり、multcomp::cld()は、モデルに定義された因子レベル順のまま CLD を付与する仕様であり、glht()を使ったTukeyではこの使用が反映されていると考えられます。

cld function - RDocumentation
Extract information from glht, summary.glht or confint.glht objects which is required to create and plot compact letter ...

emmeans::cld()の仕様

一方、emmeans::cld()には sort引数が用意されています。

cld(object, ..., sort = TRUE, ...)

ドキュメントには引数のsortに関して、次のように記載されています。

Logical value determining whether the EMMs are sorted before the comparisons are produced.

つまり、

  • 推定周辺平均(emmean)をソートしてから CLD を割り当てる
  • sort = TRUE が デフォルト

という仕様です。

このため、emmeansのCLDは常に平均値順で表示されるという挙動になります。

Help for package emmeans

StackOverflowの例

この違いは、StackOverflowのQ&Aでも確認されています。

  • emmeans + cld の結果が因子順ではなく emmean の大小順で並ぶ
  • 因子レベルを明示的に設定しても、CLD 出力順が変わる

という報告があり、これは emmeans::cld の sort = TRUE 仕様によるもの と説明されています。

Attention Required! | Cloudflare

実際に挙動を再現する

以下では、

  • 不均衡データ
  • 因子順と平均値順が一致しない状況

を意図的に作り、glht と emmeans の CLD の違いを再現します。

データ作成

set.seed(123)

dat <- data.frame(
  group = factor(rep(c("A", "B", "C"), times = c(5, 20, 50))),
  value = c(
    rnorm(5,  mean = 10,   sd = 1),
    rnorm(20, mean = 10.5, sd = 1),
    rnorm(50, mean = 11,   sd = 1)
  )
)

# 因子順を平均値順と逆にする
dat$group <- factor(dat$group, levels = c("C", "A", "B"))

tapply(dat$value, dat$group, mean)
       A        B        C 
10.61156 10.62356 10.98292 

glht + cld

library(multcomp)

fit <- aov(value ~ group, data = dat)
cld_glht <- cld(glht(fit, linfct = mcp(group = "Tukey")))

cld_glht
   C    A    B 
 "a" "ab"  "b" 

因子レベル順(C → A → B)で CLD が付与されることがわかります。

emmeans + cld

library(emmeans)

emm <- emmeans(fit, ~ group)
cld_emm <- cld(emm, Letters = letters)

cld_emm
 group emmean    SE df lower.CL upper.CL .group
 A       10.2 0.422 72     9.35     11.0  ab   
 B       10.4 0.211 72     9.99     10.8  a    
 C       11.1 0.134 72    10.79     11.3   b   

Confidence level used: 0.95 
P value adjustment: tukey method for comparing a family of 3 estimates 
significance level used: alpha = 0.05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 

emmean の大小順でCLDが付与されることが確認できました。

emmeans + cld (sort = FALSE)

cld(emm, sort = FALSE, Letters = letters)
 group emmean    SE df lower.CL upper.CL .group
 C       11.1 0.134 72    10.79     11.3  a    
 A       10.2 0.422 72     9.35     11.0  ab   
 B       10.4 0.211 72     9.99     10.8   b   

Confidence level used: 0.95 
P value adjustment: tukey method for comparing a family of 3 estimates 
significance level used: alpha = 0.05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 

glht + cld に同じ並びになることが確認できました。

まとめ

  • multcomp::cld は因子レベル順で CLD を付与する仕様
  • emmeans::cld は推定平均値順にソートして CLD を付与する仕様
  • 両者の違いは 仕様の違いであり、計算方法の誤りではない

この記事が少しでもお役に立てたら嬉しいです。

広告

Amazonアフィリエイトでブログ運営しています。
応援いただけると嬉しいです。


ネスカフェ 香味焙煎 ひとときの贅沢 スティック ブラック 20P,箱,レギュラー ソリュブル コーヒー,個包装


AHMAD TEA(アーマッドティー) クラシックセレクション ティーバッグ 20袋

タイトルとURLをコピーしました