井出草平の研究ノート

Rのmclustパッケージで潜在プロファイル分析

今回はRのmclustパッケージで潜在プロファイル分析を行う方法について解説したい。 潜在クラス分析はカテゴリカル変数、潜在プロファイル分析は(基本的には)連続変数という違いはあるものの、ケースごとのパターンからクラス分けをするのは同じである。

使い分けは次のようにするとよい。
潜在クラス分析は2値データの解釈が行いやすいため、基本的には2値データでの使用に留めるのが賢明である。
順序の無い3カテゴリの場合も潜在クラス分析をすることになる。しかし、解釈がややこしくなる。二項ロジスティック回帰分析の解釈が簡単なのに比べて多項ロジスティック回帰分析の解釈がややこしいのと同じである。とはいえ、解釈ができないわけではないので頑張ってクリアカットな結果を出すように頑張るれば使えないわけではない。

もし、順序のついているもの、つまり順序変数であれば、潜在プロファイル分析をした方がよい。
リコードをして潜在クラス分析をしている論文もあるが、潜在プロファイルを使うべきである。 例えば、リッカート尺度で計測したようなものである。「あてはまらない」-「どちらでもない」-「あてはまる」といった、5件法、7件法で計測した質問項目である。

正確に言えば、順序変数と連続変数の水準は異なるのだが、ある程度の順序があれば、連続変数とみなして計算しても、それほど問題は起こらないことがわかっている。シミュレーションによって諸説あるが、だいたい8カテゴリある順序変数であれば、連続変数と同等の結果が得られる。5件法だとさすがに連続変数と同等とはいえないのだが、潜在クラス分析をするためにリコードを行うの方が情報が失われるため、潜在プロファイル分析を行う方が、よほどまし、ということである。

今回取り上げるのはmclustパッケージの開発者たちが書いた論文の例題である。

www.ncbi.nlm.nih.gov

この例題がこちらのブログで解題されていたので、このブログ記事を参照している。

www.r-bloggers.com

データ

データは、Kaggle.comで無料で使用できるYoung People Surveyである。

library(tidyverse)
survey <- read_csv("https://raw.githubusercontent.com/whipson/tidytuesday/master/young_people.csv") %>% select(History:Pets)

Young People Surveyはだいたい以下のような感じである。

  History Psychology Politics Mathematics Physics Internet    PC `Economy Manage… Biology Chemistry Reading Geography `Foreign langua…
    <dbl>      <dbl>    <dbl>       <dbl>   <dbl>    <dbl> <dbl>            <dbl>   <dbl>     <dbl>   <dbl>     <dbl>            <dbl>
1       1          5        1           3       3        5     3                5       3         3       3         3                5
2       1          3        4           5       2        4     4                5       1         1       4         4                5
3       1          2        1           5       2        4     2                4       1         1       5         2                5
4       4          4        5           4       1        3     1                2       3         3       5         4                4
5       3          2        3           2       2        2     2                2       3         3       5         2                3
6       5          3        4           2       3        4     4                1       4         4       3         3                4
# … with 19 more variables

32の興味/趣味に関する項目が含まれていて、1(関心がない)から5(非常に関心がある)の5段階の順序変数で計測されている。

外れ値を除外する

KaggleによるとSatisficerがいるようである(Satisficerに関してはこちらを参照)。Satisficerとは同じ値を何度も選択した参加者など不適切な回答をしている者である。 carelessパッケージを使用して「文字列応答」(string responding)を識別する。マハラノビス距離で多変量の外れ値を探す。

library(careless)
library(psych)
interests <- survey %>%
  mutate(string = longstring(.)) %>%
  mutate(md = outlier(., plot = FALSE))

最大10に応答する文字列に上限を付け、α=.001のマハラノビス距離をカットオフとして外れ値を除外する。

cutoff <- (qchisq(p = 1 - .001, df = ncol(interests)))

interests_clean <- interests %>%
  filter(string <= 10,
         md < cutoff) %>%
  select(-string, -md)

外れ値を除外した分析データはinterests_cleanの中に格納された状態になっている。

潜在プロファイル分析

潜在プロファイル分析はmclustパッケージを使用して実行する。

library(mclust)
interests_clustering <- interests_clean %>%
  na.omit() %>%
  mutate_all(list(scale))
BIC <- mclustBIC(interests_clustering)

BICをプロットする。

plot(BIC)

f:id:iDES:20191210162844p:plain

この分析の場合、プロットだけでは、ラインが近接しているので見にくいので、上位3つのBICsummary()を使って表示させる。

summary(BIC)

下記のように表示される。

Best BIC values:
            VVE,3       VEE,3      EVE,3
BIC      -75042.7 -75165.1484 -75179.165
BIC diff      0.0   -122.4442   -136.461

最も良好な値を取っているのはVVE,3である。とはいえ、この3つの統計量にそれほどの違いはない。
ガウス共分散行列の各モデルを視覚的に表現すると下記のようになる。こちらの論文に掲載されている図である。

f:id:iDES:20191210162932p:plain

VEE,3は分布の形状が等しくなるように制約をかけているので、実際に分析するのはこのモデルがよいと考えられる。
VEE,3は以下のようなモデルである。

mod1 <- Mclust(interests_clustering, modelNames = "VEE", G = 3, x = BIC)
summary(mod1)

結果は以下。

---------------------------------------------------- 
Gaussian finite mixture model fitted by EM algorithm 
---------------------------------------------------- 

Mclust VEE (ellipsoidal, equal shape and orientation) model with 3 components: 

 log-likelihood   n  df       BIC       ICL
      -35455.83 874 628 -75165.15 -75216.14

Clustering table:
  1   2   3 
137 527 210 

これらの統計量単体で適切性は判断できないが、クラスタリングの結果、極端に少ないグループがないことが確認できる。

ICL: Integrated Completed Likelihood (ICL)

BICのほかにICLでもモデルのフィッティングを見る。

ICL <- mclustICL(interests_clustering)
plot(ICL)
summary(ICL)

結果をプロットすると以下のようになる。

f:id:iDES:20191210163018p:plain

Best ICL values:
             VVE,3        VEE,3      EVE,3
ICL      -75134.69 -75216.13551 -75272.891
ICL diff      0.00    -81.44795   -138.203

グラフからも、ICLのサマリからも、BICと同じ傾向が確認できる。 ICLで最もフィッティングがよいのはVEE,3である。

以上の分析からVEE,3が最も適切であると判断できる。根拠となるのは以下の3点である。

  1. 分布の形状が同じになる制約
  2. BICでVVE,3とほとんど変わらず2番目にフィッティングが良好なモデル
  3. ICLで最もフィッティングが良好なモデル

BLRT

潜在プロファイル分析でもBLRTを行う。 モデルの選択ではなく、クラス数の選択であり、BICやICLで確認していることとは異なるので注意が必要である。

mclustBootstrapLRT(interests_clustering, modelName = "VEE")

結果は以下。

------------------------------------------------------------- 
Bootstrap sequential LRT for the number of mixture components 
------------------------------------------------------------- 
Model        = VEE 
Replications = 999 
              LRTS bootstrap p-value
1 vs 2    197.0384             0.001
2 vs 3    684.8743             0.001
3 vs 4   -124.1935             1.000

3 vs 4でP-Valueが有意ではなくなっており、4クラスモデルで改善が見られなかったということなので、3クラスモデルが良いという提案である。
BIC、ICLはどちらも3クラスモデルを提案していたので、3クラスモデルで間違いなさそうである。

ちなみにBLRTが良いと言っているのは、Mplus開発グループの論文Nylund,Asparouhov, Muthén(2007)である。
https://www.statmodel.com/download/LCA_tech11_nylund_v83.pdf

プロット

各プロファイルの平均値を抽出し、+1 SDを超える値をトリミングする。この作業をしてないとプロットで枠外へはみ出るので必要になる作業である。

library(reshape2)

means <- data.frame(mod1$parameters$mean, stringsAsFactors = FALSE) %>%
  rownames_to_column() %>%
  rename(Interest = rowname) %>%
  melt(id.vars = "Interest", variable.name = "Profile", value.name = "Mean") %>%
  mutate(Mean = round(Mean, 2),
         Mean = ifelse(Mean > 1, 1, Mean))

ggplot2でプロットを行う。

library(ggplot2)
p1<- means %>%
  ggplot(aes(Interest, Mean, group = Profile, color = Profile)) +
  geom_point(size = 2.25) +
  geom_line(size = 1.25) +
  scale_x_discrete(limits = c("Active sport", "Adrenaline sports", "Passive sport",
                              "Countryside, outdoors", "Gardening", "Cars",
                              "Art exhibitions", "Dancing", "Musical instruments", "Theatre", "Writing", "Reading",
                              "Geography", "History", "Law", "Politics", "Psychology", "Religion", "Foreign languages",
                              "Biology", "Chemistry", "Mathematics", "Medicine", "Physics", "Science and technology",
                              "Internet", "PC",
                              "Celebrities", "Economy Management", "Fun with friends", "Shopping", "Pets")) +
  labs(x = NULL, y = "Standardized mean interest") +
  theme_bw(base_size = 14) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "top")
p1

f:id:iDES:20191210163120p:plain

赤のグループは科学に興味があり、青のグループは芸術と人文科学に大きな関心があり、緑のグループは、科学と芸術の両方に関心がないように見えるが、他のことにある程度関心があるように捉えられる。

そこで、1クラスを科学(Science)、2クラスを無関心(Disinterest)、3クラスを人文(Arts & Humanities)とする。
それぞれのクラス名を代入したプロットに書き換える。上のコードとの違いはmutateでクラス名を入れているだけである。

p2 <- means %>%
  mutate(Profile = recode(Profile, 
                          X1 = "Science: 16%",
                          X2 = "Disinterest: 60%",
                          X3 = "Arts & Humanities: 24%")) %>%
  ggplot(aes(Interest, Mean, group = Profile, color = Profile)) +
  geom_point(size = 2.25) +
  geom_line(size = 1.25) +
  scale_x_discrete(limits = c("Active sport", "Adrenaline sports", "Passive sport",
                              "Countryside, outdoors", "Gardening", "Cars",
                              "Art exhibitions", "Dancing", "Musical instruments", "Theatre", "Writing", "Reading",
                              "Geography", "History", "Law", "Politics", "Psychology", "Religion", "Foreign languages",
                              "Biology", "Chemistry", "Mathematics", "Medicine", "Physics", "Science and technology",
                              "Internet", "PC",
                              "Celebrities", "Economy Management", "Fun with friends", "Shopping", "Pets")) +
  labs(x = NULL, y = "Standardized mean interest") +
  theme_bw(base_size = 14) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "top")
p2

f:id:iDES:20191210163135p:plain

図で確認すると、各クラスの特徴がわかりやすくなる。
いろいろと傾向が読み取れるが、面白いのは、科学(Science)のクラスに属している人は映画館/演劇とセレブに興味がないというのは世情に疎いということだろうか。思い当たる節は確かにある。バリバリの理系の人と話をするときには、芸能話題を選ぼうとは思わない。日本であれば何かのオタクである確率が高い気がする。人文(Arts & Humanities)クラスが経済管理(Economy Management)に興味がない、と出ているが、確かに人文系と経済は相性が悪い。人文系には、経済学的な発想がないというのもあるし、個人的な金銭管理にもあまり興味がないように思う。

余談だが、mclustのブートストラップの反復回数は999回のようである。マシンパワーにもよるが分析は多少時間がかかる。
以前、99について書いたが最近は999ルールなのかもしれない。

追記

このエントリではパイプ演算子を使った書式で書いてある。
パイプが読めないという場合には、下記のエントリに標準書式でのコードを書いておいた。

ides.hatenablog.com

RからMplusを使う Rですべて完結させる

RからMplusが使えるようになるMplusAutomationパッケージについてのエントリ2つ目。
前回はデータをMplus形式に変換する方法について解説した。

ides.hatenablog.com

今回も下記の条件で書いている。

  1. RStudioを使っている
  2. ファルダパスに日本語が混じっていない

今回はR上からMplusの分析を行う方法について解説する。

分析データと分析コード

パッケージのガイドに掲載されている簡単な例を実行する。 使用するデータはmtcarsである。Rにデフォルトで入っているので比較的有名なデータである。

mtcars function | R Documentation

head(mtcars)

以下のようなデータである。

                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

今回使用するのは4つの変数。

  • mpg...マイル/ガロン(燃費)
  • hp...Gross horsepower...総馬力
  • wt...重さ
  • disp...排気量

Mplusの分析コードは下記のように書く。

TITLE: Path Mode;
DATA: FILE = "Path_model.dat";
MODEL: 
     mpg ON hp;
     wt ON disp;
OUTPUT:"CINTERVAL;

これをR上から実行する。

Mplusの分析コマンドをR上から実行

library(MplusAutomation)
pathmodel <- mplusObject(
   TITLE = "Path Mode;",
   MODEL = "
     mpg ON hp;
     wt ON disp;",
   OUTPUT = "CINTERVAL;",
   rdata = mtcars)
fit <- mplusModeler(pathmodel, modelout = "Path_model.inp", run = 1L, hashfilename = FALSE)

このスクリプトを走らせると、Rstudioの作業フォルダ内にデータの.datファイル、分析コードファイル.inp、分析結果のファイル.outが出力される。

変更するのは下記の点である。

  • コロンはイコールにする
  • ダブルクォーテーションで囲う
  • 文末にコンマ

hashfilename= FALSEにすると、inpファイル名と同じデータファイル(.dat)が作成される。

結果をRに読み込む

Mplusの結果はpath_model.outに出力されている。
結果を見たい場合は、直接見てもよいだろう。

Rへ結果を返したいときには、下記の関数を使う。

res<-readModels()

結果をresに格納する。 走らせた分析が1つでout形式ファイルが1つの時にはこの方法が取れる。

結果は下記のように引数を指定すると表示できる。
まずは統計量。

res$summaries

下記のようにやや混沌とした形で出力される。

  Mplus.version       Title AnalysisType   DataType Estimator Observations NGroups NDependentVars NIndependentVars NContinuousLatentVars
1             8  Path Mode;      GENERAL INDIVIDUAL        ML           32       1              2                2                     0
  Parameters ChiSqM_Value ChiSqM_DF ChiSqM_PValue ChiSqBaseline_Value ChiSqBaseline_DF ChiSqBaseline_PValue       LL UnrestrictedLL   CFI
1          7       15.564         2         4e-04             106.604                5                    0 -101.059        -93.277 0.867
    TLI     AIC     BIC    aBIC RMSEA_Estimate RMSEA_90CI_LB RMSEA_90CI_UB RMSEA_pLT05  SRMR     AICC       Filename
1 0.666 216.117 226.377 204.555           0.46         0.266         0.685       0.001 0.136 220.7837 path_model.out

BICだけ取り出したいときは更にBICをつける。

res$summaries$BIC

こちらはシンプルでよい。

226.377

推定結果は次のように書くと返される。

res$parameters$unstandardized

出力。

         paramHeader param    est    se est_se  pval
1             MPG.ON    HP -0.065 0.009 -6.889 0.000
2              WT.ON  DISP  0.006 0.001  8.739 0.000
3            WT.WITH   MPG -1.020 0.384 -2.657 0.008
4         Intercepts   MPG 29.586 1.529 19.346 0.000
5         Intercepts    WT  1.816 0.180 10.112 0.000
6 Residual.Variances   MPG 14.045 3.524  3.986 0.000
7 Residual.Variances    WT  0.209 0.056  3.751 0.000

95%信頼区間ci.を挟むんで$parameters$ci.unstandardizedと書くと返される。

texregパッケージできれいに表示

きれいに表示するにはtexregパッケージが使用できるようだ。

library(texreg)
screenreg(fit, summaries = c("Observations", "CFI", "SRMR"), single.row=TRUE)

下記のように整えて出力される。

==================================
                  Model 1         
----------------------------------
 MPG<-HP          -0.06 (0.01) ***
 WT<-DISP          0.01 (0.00) ***
 WT<->MPG         -1.02 (0.38) ** 
 MPG<-Intercepts  29.59 (1.53) ***
 WT<-Intercepts    1.82 (0.18) ***
 MPG<->MPG        14.04 (3.52) ***
 WT<->WT           0.21 (0.06) ***
----------------------------------
Observations      32              
CFI                0.87           
SRMR               0.14           
==================================
*** p < 0.001, ** p < 0.01, * p < 0.05

モデルを比較する

Rのlmやglmで使用するupdate関数が利用できる。 下記のように新しいパスを追加する。

pathmodel2 <- update(pathmodel, MODEL = ~ . + "
    mpg ON disp;
    wt ON hp;")
fit2 <- mplusModeler(pathmodel2, modelout = "model2.inp", run = 1L, hashfilename = FALSE)

この結果を先ほどのモデルと比較する。

screenreg(list(
  extract(fit, summaries = c("Observations", "CFI", "SRMR")),
  extract(fit2, summaries = c("Observations", "CFI", "SRMR"))),
  single.row=TRUE)

出力。

====================================================
                  Model 1           Model 2         
----------------------------------------------------
 MPG<-HP          -0.06 (0.01) ***  -0.02 (0.01)    
 WT<-DISP          0.01 (0.00) ***   0.01 (0.00) ***
 WT<->MPG         -1.02 (0.38) **   -0.73 (0.26) ** 
 MPG<-Intercepts  29.59 (1.53) ***  30.74 (1.27) ***
 WT<-Intercepts    1.82 (0.18) ***   1.68 (0.19) ***
 MPG<->MPG        14.04 (3.52) ***   8.86 (2.21) ***
 WT<->WT           0.21 (0.06) ***   0.19 (0.05) ***
 MPG<-DISP                          -0.03 (0.01) ***
 WT<-HP                             -0.00 (0.00)    
----------------------------------------------------
Observations      32                32              
CFI                0.87              1.00           
SRMR               0.14              0.00           
====================================================
*** p < 0.001, ** p < 0.01, * p < 0.05

95%信頼区間を併記する場合にはcis=TRUEをオプションに追加しておく。

screenreg(list(
  extract(fit, cis=TRUE, summaries = c("Observations", "CFI", "SRMR")),
  extract(fit2, cis=TRUE, summaries = c("Observations", "CFI", "SRMR"))),
  single.row=TRUE)

結果省略。

パッケージの限界

上記のように書くと非常に便利な機能のように感じられるが、実際の所、すべての分析に対応しているわけではなさそうである。
因子分析を走らせてみたところ、結果のMplusが分析するとこまではできるが、Rへの結果のリターンができなかった。 Mplusに分析させるまでは、おそらくシンプルではないモデルであっても、可能だがRへ結果を返せないのだ。

Rは図表を整えるパッケージが揃っているので、RにMplusがデータを渡すことができれば、かなり重宝するだろう。
僕が理解できる範囲では一部の分析結果にとどまっている。

MplusAutomationパッケージでMplusコマンドを書くとややこしくなる。
それであれば前回の変換編で書いたように、データだけ書いてMplusで実行ファイルを書いた方がよいと思う。

RでMplusの分析コードを書いてMplusに計算させるというのは、実用性はそれほど高くなく、やはり、結果をRで読み込めることの方が重要性は高い。
結果の読み込みができるとパーフェクトに近いパッケージになるように思われた。

参考までに こちらで行った因子分析をMplusAutomationパッケージの形式で書き換えたものを掲載しておこう。

library(psych)
data(bfi)
FAmodel <- mplusObject(
  TITLE = "Exploratory Factor Analysis by Mplus via R, using NEO data.;",
  VARIABLE = "USEVARIABLES = A1-A5 C1-C5 E1-E5 N1-N5;",
  ANALYSIS = "TYPE = EFA 4 6;
              ESTIMATOR = ML;
              ROTATION = oblimin;
              PARALLEL = 50;",
  PLOT = "TYPE = plot2;",
  OUTPUT = "residual;",
  usevariables = c("A1", "A2", "A3", "A4", "A5", "C1", "C2", "C3", "C4", "C5",
                   "E1", "E2", "E3", "E4", "E5", "N1", "N2", "N3", "N4", "N5", 
                   "O1", "O2" ,"O3", "O4", "O5"),
  rdata = bfi)
FA_fit <- mplusModeler(FAmodel, modelout = "bfi.inp", run = 1L, hashfilename = FALSE)

RからMplusを使う ファイル変換編

RからMplusが使えるようになるMplusAutomationパッケージというものがある。

cran.r-project.org

有用な関数が複数含まれているので使い方がいくつかあるが、今回はRを使ってMplusのデータとコードの一部を作る方法を紹介しよう。

RStudioを利用する

RとMplusのユーザーであれば、RStudioを使っていると思うので、RStudioが導入されている前提で話を進める。

RStudioの使い方はこちらを参照のこと。

www.idesohei.net

Mplusの分析ファイルはどこに置けばいいの?

日本語で得られる情報では、Mplusの作業ディレクトリは絶対パスで設定しているものばかりだがRStudioと同じく、パスの指定は不要である。 ただ、2バイト文字をパスに含めないという違いがあるだけである。 詳しくはリンク先のMplusの作業ディレクトリ解説を参照のこと。

ides.hatenablog.com

Mplusの形式でのデータ書き出し

psychパッケージにあるbfiというデータをMplus形式で書きだす。

library(MplusAutomation)
library(psych)
data(bfi)

bfiはこのブログではよく使っている5因子パーソナリティのデータIPIP-NEOである。 データの詳細はこちらを参照のこと。 http://ides.hatenablog.com/entry/2019/03/19/093726

変数名を抽出する

変数すべてを書き出すことはおそらく稀で、分析に必要なデータだけを書き出すことが多い。 そこで、書き出す変数の指定をするために変数名を抽出しておいた方が便利だ。

variable.names(bfi)

以下のように出力される。

 [1] "A1"        "A2"        "A3"        "A4"        "A5"        "C1"        "C2"        "C3"        "C4"        "C5"       
[11] "E1"        "E2"        "E3"        "E4"        "E5"        "N1"        "N2"        "N3"        "N4"        "N5"       
[21] "O1"        "O2"        "O3"        "O4"        "O5"        "gender"    "education" "age"     

Mplusデータ形式として出力

因子分析だけする場合には、"gender","education","age"の変数は使わないのでオミット(ドロップ)させる。保持する変数をしている場合はkeepColsと書く。

prepareMplusData(bfi, filename="bfi.dat", 
                dropCols=c("gender","education", "age"),
                overwrite=T)
  • bfi...出力するデータ
  • filename...出力するデータ名
  • keepCols...保持する変数
  • dropCols...保持しない変数...keepとdropはどちらかのみ指定

Mplusで使用するdatが同じディレクトリ(フォルダ)上に出力される。 Rの出力は下記のように出る。

DATA: FILE = "bfi.dat";
VARIABLE: 
NAMES = A1 A2 A3 A4 A5 C1 C2 C3 C4 C5 E1 E2 E3 E4 E5 N1 N2 N3 N4 N5 O1 O2 O3 O4 O5; 
MISSING=.;

これは、Mplusの分析コードであり、inp形式データの前半部分である。
つまり、 Mplusのコードの前半部分が自動生成されるのだ。

意外にMplusのコードでミスが出やすいのがこの箇所である。ANALYSISやMODELの部分はしっかり考えて書くので、割と間違えない。

データ出力だけ使用する場合には、inpファイルは通常の方法で作成する。

ちなみに、Mplusで因子分析をするには以下のような分析コードになる。

TITLE:""
DATA: FILE = "bfi.dat";
VARIABLE: 
    NAMES = A1 A2 A3 A4 A5 C1 C2 C3 C4 C5 E1 E2 E3 E4 E5 N1 N2 N3 N4 N5 O1 O2 O3 O4 O5; 
    MISSING=.;
ANALYSIS:
    TYPE = EFA 3 6;
    ESTIMATOR = ML;
    ROTATION = oblimin;
    PARALLEL = 50;
PLOT: TYPE = plot2;
OUTPUT: residual;

MplusAutomationの使い方としてはいくつかあるが、現実的にはここまでをRで行うのがいいのではないかと思う。
僕は今までExcelでMplus用のデータを作成していた。手間がかかるし、手間がかかればミスも出る可能性がある。なによりも、何をどのように処理したか、記録が取れないのが最も問題だった。個人的にはかなりの福音である。

1台のパソコンで異なったバージョンのMplusを使うには

今日は小技の紹介。
1台のパソコンで異なったバージョンのMplusを使うにはどうしたらよいか、という話である。

このようなことを試みた人はあまりいないかもしれないが、Mplusの異なったバージョンを同じPCにインストールしてもうまく使えない。 今回のはその解決法である。

Mplusの仕組み

Mplusのエディタは下記のものだ。

f:id:iDES:20191203005506p:plain:w400

Mplusの正式な名称はわからないが、いわゆるエディタの類なので、本エントリではエディタと呼ぶことにする。

実はMplusの本体はこれではない。エディタはフロントエンドにすぎない。
本体はこちらである。

f:id:iDES:20191203005841p:plain:w400

分析を実行すると、黒いウィンドウが出て計算をしているやつである。

Mplusはエディタで書いた分析の命令を本体に送って計算させて、終了するとエディタに返す、という仕組みである。

異なったバージョンのMplusを使うために必要な2つのこと

以下の2つを実施すると、異なったバージョンのMplusが利用可能である。

  1. MplusをそれぞれMplus8やMplus7といったフォルダにインストールする
  2. Pathを使うバージョンを変更するごとにMplus8やMplus7というフォルダに変更する

インストール場所をデフォルトから変更する(インストール時)

64bit版の場合、Mplusのデフォルトのインストール場所は下記の場所である。

C:\Program Files\Mplus

これを"Mplus8"というようにバージョンの番号をいれる。

C:\Program Files\Mplus8

Pathを変更する

つぎにPathを変更作業を行う。 Mplusをインストールするとpathが自動的に設定される。

f:id:iDES:20191203010520p:plain

この図ではMplusのPathはC:\Program Files\Mplusに通っている。
この場所がMplusの本体の格納場所を示している。
エディタから本体へ分析命令をどこに送ればいいか、ということを指定する。

したがって、このPathはMplus8に変えたり、Mplus7に変えれば、異なったMplusで分析ができる。

Pathの変え方は以下のページで解説がされている。

proengineer.internous.co.jp

どのバージョンで分析したか

分析結果のファイルである".out"の先頭行に書かれてある。
例えばこんな感じである。

Mplus VERSION 7
MUTHEN & MUTHEN
12/03/2019  08:40 AM

Mplus7で分析しているつもりでも、Mplus6に分析が送られていた、ということも起こりうるので、outファイルの先頭行には注意しておこう。

春日武彦は腹の底で何を考えているか

「あけぼのばし自立研修センター」の件で精神科医である春日武彦氏が注目されている。
この訴訟では、成仁病院の医師が逮捕監禁罪で訴えられている。

f:id:iDES:20191202040857p:plain https://twitter.com/pentaxxx/status/1200740076600250368

「あけぼのばし自立研修センター」はひきこもりの「引き出し屋」である。
本人の許諾なく、連れ去り、施設に閉じ込めるのは、拉致と監禁であり、刑事罰の対象となる。

拉致監禁をしたのは「あけぼのばし自立研修センター」であり、「成仁病院」はセンター経由で強制入院を実施したようだ。
入院の際には、法定要件を満たしておらず、全裸にオムツをはかされて3日間身体拘束され、入院期間は50日に及んだと告訴した男性は述べている。

春日武彦の肩書

現在は「顧問」と名乗っており、制度的には「管理者」のようだ。
https://www.nisseikyo.or.jp/hospital_search/hospital_Info.php?id=1224&dt=20161209143629

ただ、今年の秋くらいまでの肩書は院長であった。
https://www.igaku-shoin.co.jp/paperDetail.do?id=PA03335_03
http://rakukai.com/2019/05/29/getsurei-20190615/

春日武彦氏は院長ではないという声がある*1ようだが、問題の訴訟の時には院長だったのだと思われる。 告訴された医師が春日武彦氏なのか不明である。

春日武彦氏ではなかったとしても、病院所属の医師個人が、院長の許可なしに他の団体との提携をしていることは考えにくい。
本人の関与がなかったとしても、管理的な立場にいる者の責任は問われるべきであろう。

春日武彦精神科医は腹の底で何を考えているか』

同書206頁から「引きともりは「心の病」か」というタイトルで、ひきこもりの話が書かれている。

小手先の解決法を模索してみても効果はない。現実的な対応は、まずは家族の硬直した価値観を変えることから始まるだろう。ただしいきなり変えることは困難だし、どうしてもある程度の時間経過が必要だろう、おそらく年単位の。そしてじっくりと時聞をかけて本人と親、双方が「ああ、もっと別な考え方、別な生き方だっであるんだ」と思えるようになって互いに牽制し合うことから脱却した状態を、「和解」と称することになるだろう。

そういった意味では、引きこもりは病というよりは家族病理を和解へと至らしめるためのプロセスと見倣すべきかもしれない(98|和解という形を、ゴールインとして設定することが実際的であると考える医師)。(pp.201)

ひきこもりの支援論として、変なことを言っているようには思えないし、拉致監禁に関わっている人の感じもこの文章からは感じ取れない。

池上正樹×春日武彦 対談

news.livedoor.com

ジャーナリストの池上正樹氏との対談。
「ゴールを設定せずに子供の話を聞いてあげてほしい」と春日武彦氏は述べている。 先の本でもひきこもりは親子の和解がメインテーマであったが、この対談でも同じスタンスで語られている。
ちなみに、2019年8月27日の記事で当時の肩書は成仁病院院長である。

ひきこもりの拉致監禁に手を貸していたとなると「和解」とは程遠い臨床をしていたことになる。
親の依頼で、本人の許諾なしに、拉致監禁をした後に、親子の和解などできるものだろうか。 拉致された側は一生、親を許さないだろう。

行政主催のイベントの講師に

春日武彦氏は東京を中心に、行政主催のイベントで、ひきこもり関連の講師として頻繁に登壇しているようである。
例えば、今年は文京区や大田区で講演をしていることが確認できる。

言動と行動の不一致が明らかであると、春日武彦が「腹の底で何を考えているか」が気になるところである。
次回の講演では「春日武彦は腹の底で何を考えているか」というテーマで、是非、ひきこもり支援の本音を語っていただきたいものである。

*1:斎藤環さんのツイートのレスを参照

Stata LCA プラグインを使用した潜在クラス分析 導入偏[Stata]

Stata15から標準機能で潜在クラス分析ができるようになっている。

ただ、基本的な機能しかないため、Stataの標準機能の潜在クラス分析は現在のところ実用に耐えられない。そこで、面倒な作業が必要になるが、Lanzaらが作成したStata LCA プラグインを使わざるを得ない。

Stataの標準機能

Stataの標準機能の潜在クラス分析は下記のエントリで解説を行っている。

ides.hatenablog.com

Stataの標準機能にかけているものは2つある。

  1. BLRTが計算できない。 潜在クラス分析を使った論文で求められる統計量であるBLRTがStataの標準機能では計算できない。無料のRでも少し工夫をすれば計算できる(参照)ので、有料であるStataを選ぶのは合理的な選択とは言いづらい。

  2. モデルの拡張ができない。 潜在クラス分析はクラス分け(グルーピング)をしただけでは、興味深い結果にならないことが多い。実際には、他の変数との関連性を検討することが必要になる。しかし、Stataの標準機能ではこのモデルの拡張ができない。

ここの2つの理由から現在のStataの標準機能での潜在クラス分析は勧められない。

そこで、Lanzaらの作ったプラグインを使う必要が出てくるのである。ただ、パッケージではなく、プラグインであるため、導入と運用にはハードルが少し高い。このハードルを越えられれば、MplusやLatent Goldなどのソフトウェアと同程度の分析が可能になる。

Stata LCA プラグインの注意点と他のソフトウェア

Windowsにしか対応していない。

  • Mplus Macにも対応。現在の最新技術まで利用できる。

  • Latent Gold Windowsのみ対応。現在の最新技術まで利用できる。GUIで操作性が非常によい。アカデミックでも30万弱、一般で80万とかなり高額。

  • SAS LCA PROC SAS用にLanzaらが配布しているプラグイン。無料である。ただしSASの方が高額である。SASMacにも対応しているが、LanzaらのプラグインWindowsのみ対応。もちろん無料版のSAS University Editionには対応していない。

Macの人は1) Mplusを使う(他のソフトウェアの使用をあきらめる)、2) デュアルブートWindowsを動かす、3)Winodws機を購入するという3点が選択肢になる。

Stata LCA プラグインのダウンロード

www.methodology.psu.edu

上記のページから32-bit版/64-bit版のファイルをダウンロードする。
Windowsが64bitに対応していれば、どちらでもよいが、BLRTをおなうことを想定すると、計算時にメモリを多く使用するため、メモリの使用に制限がない64-bit版の方がおそらくよいだろう。

プラグインのインストール

ダウンロードしたファイルを解凍

ファイルを常時設置するディレクトリ(フォルダ)が必要になる。ファイルをどこに置くかはよく考えた方がよいだろう。マニュアルの例は次の場所。“D:\project\Stata_lca\Release\” 。
一般的にこのようなソフトウェアは日本語など2バイト文字を含むアドレス上に置くと動作しないことが多いため、Windowsのユーザー名を日本語で入れている人はユーザーフォルダは避けた方がよい。

下記で変更を行う"lca.do"、"doLCA.ado"は解凍フォルダに入っているため、解凍したファイルすべてを自分で決めた場所のフォルダに移動する。

doファイルの設定

doファイルは毎回設定をする必要があるので、後で説明。

"doLCA.ado"ファイル内のパスを変更

  1. ファイル"doLCA.ado"を開く。 注:Stataの[ファイル]→[開く]から。ファイルをダブルクリックしても開かない。
  2. コードの一番最後の行(869行目)の"lca.dll"のパスを先ほどと同じように変更する。 例では“D:\project\Stata_lca\Release\lca.dll”。必ず"lca.dll"までを含めたパスを書く必要がある。
  3. 変更を保存。

doファイルの設定

同梱されている"lca.do"ファイルは5つの例題が掲載されている。動作確認するには例1だけ走らせるのがよいだろう。

  1. "lca.do"ファイルをコピーし、"lca_ex01.do"など任意の名前にリネームする。
  2. 22行目(//matrix list r(rhoSTD))までが例1なので、任意の名前に変更したファイルの23行目以降削除する。これで例1だけのdoファイルになる。
  3. コードの5行目で、パス“D:\project\Stata_lca\Release\”をさきほどファイルを置いた場所に変更する。この行には“/CHANGE THIS PATH TO MATCH THE FILE LOCATION ON YOUR MACHINE/”という文字が書きこまれてあるのですぐに発見できるはずだ。
  4. 変更を保存し、doファイルを実行する。

結果

例1はこれでとりあえず走るはずである。

scalars:
                 r(df) =  4031
        r(EntropyRsqd) =  .8585102062978721
         r(EntropyRaw) =  227.7190382066842
        r(AdjustedBIC) =  979.1363404006836
               r(caic) =  1246.403913372541
                r(bic) =  1182.403913372541
                r(aic) =  868.3075755176842
           r(Gsquared) =  740.3075755176842
      r(loglikelihood) =  -3366.110782824834
          r(iteration) =  591

matrices:
             r(rhoSTD) :  24 x 5
                r(rho) :  24 x 5
           r(gammaSTD) :  1 x 5
              r(gamma) :  1 x 5

. matrix list r(gamma)

r(gamma)[1,5]
       Class1     Class2     Class3     Class4     Class5
r1  .67019096  .06416831  .14781815  .06554844  .05227414

. matrix list r(gammaSTD)

r(gammaSTD)[1,5]
       Class1     Class2     Class3     Class4     Class5
r1  .02334551  .01335266  .02312087  .00856993  .01521007

所属確率が出力されないのは21行目の"matrix list r(rho)"が"//"でミュートされているためである。
実際に分析する場合には、"//"を取り除く。標準化した結果が欲しい場合には、22行目の//matrix list r(rhoSTD)のミュートを外す。

実行に必要になるもの

2回目以降の分析で必要になるものが3ある。

  1. doファイル スクリプトを書き込むのはdoファイルである。

  2. データファイル 同梱の"LcaSampleDataset.txt"を開くとデータの構造がわかるはずである。変数名は入れず、データは数字で入力。データとデータの間は半角スペースで区切る。

以下のような形式である。

1 3 15 2 2 2 2 2 2 2 2 2 2 2 2 1
1 1 17 2 2 2 2 2 2 2 2 2 2 2 2 2
1 0 17 2 2 2 1 2 2 2 2 2 2 2 2 3
2 2 19 2 2 2 1 2 2 2 2 2 2 2 2 4
1 4 17 2 2 2 2 2 2 2 2 2 2 2 2 5
2 2 15 2 2 2 2 2 2 2 2 2 2 2 2 6
2 5 15 2 1 1 1 1 2 2 2 2 2 2 2 7
2 1 11 2 2 2 2 2 2 2 2 2 2 2 2 8
1 2 14 1 2 2 2 1 2 2 2 2 2 2 1 9
1 0 17 2 2 2 2 2 2 2 2 2 2 2 2 10

3. 変数名ファイル データファイルと同じ名前で作成する。拡張子はdct。変数名はこのファイルに格納する。

同梱の"LcaSampleDataset.dct"は下記の内容が書かれている。

dictionary using LcaSampleDataset.txt
{
   gender TVHours MomEduc SmokedBefore13 DailySmoke DroveDrunk
   DrankBefore13 BingeDrink MarijuanaBefore13 CocaineEver
   GlueEver MethEver EcstasyEver SexBefore13 ManyPartners ID
}

表示できないので改行をしているが、実際には改行はしてはいけない。 編集はテキストエディタを利用する。こちらもdoファイルと同様に、分析ごと(正確には新しいデータを使うごと)に設定が必要になる。

テキストエディタ

テキストエディタを使ったことがない人には下記の2つのソフトウェアの導入をお勧めする。

多機能のテキストエディタAtomがよい。

atom.io

ただし、Atomはプログラミングからメモまで多くの機能を持った多機能エディタで設定もそれなりに勉強が必要なので、dctファイルの編集のためだけに導入するのはハードルが高い。

シンプルな機能のみに対応したテキストエディタTeraPadがよいと思う。

tera-net.com

AtomTeraPadともフリーウェアである。
秀丸EmEditor、SublimeText3などでもよい。使い慣れた利用するとよいと思う。

トリンテリックス(ボルチオキセチン)と性機能障害

トリンテリックス(ボルチオキセチン)について一つ気づいていなかったことがある。下記の記事を読んで気付いた。

www.mdmag.com

性機能障害が他の抗うつ薬に比べて低いという補足記述が2018年10月22日にFDAに受理されたという記事である。

研究

元になった研究はJacobsen et al.(2015)である。

www.ncbi.nlm.nih.gov

セレクサ、パキシルジェイゾロフトで治療され反応した参加者の薬を無作為にトリンテリックス(10/ 20mg; n = 225)とレクサプロ(10 20mg; n = 222)に切り替えた。期間は8週間である。
性機能の尺度はCSFQ-14(the Changes in Sexual Functioning Questionnaire Short Form)、抗うつ剤の有効性はMADRS、全般的な評価としてCGIを使用した。
性機能障害はレクサプロに比較して少なかった。また、両方のグループで抗うつ薬の有効性は継続していた。

世界で市販されている性機能障害の出にくい抗うつ剤

  • リフレックス・レメロン(ミルタザピン)
  • トリンテリックス(ボルチオキセチン)
  • ブプロピオン(未承認)
  • アゴメラチン(未承認)
  • ビラゾドン(未承認)

性機能障害が少ない抗うつ薬は海外ではいくつか選択肢がある。しかし日本では2つしかない。

リフレックス・レメロンは眠気によって日中のパフォーマンスが低下することなど、副作用が原因で服薬が難しい人が多い。 日本では、高齢者がターゲットなのではとブログで書いたが、性機能障害もターゲットであるのは間違いなさそうである。

研究者コメント

バージニア大学医学部精神医学および神経行動科学科の主任研究調査員であるアニタ・クレイトン医学博士のコメントが掲載されている。

性機能障害は、SSRIを処方されたときにうつ病と闘う最も一般的で厄介な副作用患者の1人です。これらの厄介な副作用を具体的に調べるために研究を設計しました。うつ病の治療効果を失わずに、性的副作用が潜在的に少ない薬剤に変更することは、うつ病患者にとって重要な選択肢です。