霞と側杖を食らう

ほしいものです。なにかいただけるとしあわせです。[https://www.amazon.jp/hz/wishlist/ls/2EIEFTV4IKSIJ?ref_=wl_share]

印度の子供がなりたいものはラジャラジャマハラジャー

先日、眼鏡を新調した。自動車免許の更新期限が近付いていて、このままでは更新時の視力検査で引っかかると思い、レンズの度を上げなければならなかったのだ。おかげで、遠くの文字もくっきり見えるようになり、免許も無事更新できた。更新できたのは良かったが、眼鏡を外すと、目の前にあるPCのスクリーンすら、文字がぼやけて見えてしまうという現実に気付かされ、少しだけ憂鬱になった。

この世界では、遠くにあるものはぼやけて見えるし、近くにあるものはくっきり見える。これは物理的にも然りだが、精神的にもまた然りだ。関心のあるアイドルグループであればメンバー全員の見分けがつくだろうが、興味のないバンドの曲なんてどれも一緒に聞こえてしまう。人間の認知能力というものは、そんなものだ。一方で、近いからといって、近過ぎるとこれまた見えにくくなる。自分の顔についてる鼻はほとんど見えやしない。自分とは何者か認知することもまた困難を極める。自分を感知するには、鏡や水面に映したり、他者からの反応や言葉の跳ね返りを見るしかない。

こんなわけのわからないことを書き連ねているのは、どうも最近、自分を見失っていると感じているからだ。最も近くにあるはずの自分がよく見えなくなっている。6月頃から何かを喪失している気がしている。自分の立ち位置が分からなくなっている。疫病騒動から来るストレスも一因なのだろうが、もう1つの原因として、周りの友人達のライフステージの変化による影響が考えられる。人生ゲームで言えば、私は職業決定マスを通過したばかりなのに、周りは結婚マス、出産マス、転職マスを踏破している。そんな状況なものだから自分の居場所を見失っているような気がしている。どうあるべきか、どう生きるべきかの再考の強迫観念に苦しんでいるように思う。

2年前の就活をしている時期に、自分が何者かという話を書いていた(https://moratoriamuo.hatenablog.com/entry/2018/05/14/031639)。2年経った今も、自分が何者かなんて分かっていない。人と話したり、本を読んだり、映画を観たりして、自分がどこにあるのか、どうあるべきかをを日々探っている。長い鼻をあけ方の秋風にぶらつかせながら。

Netflix/YouTube/AmazonPrimeVideo

おうち時間だとかSTAY HOMEが掲げられるこんな御時世なもんで、家に引き籠って動画配信サービスで動画を垂れ流していることが増えた。Youtubeで一発撮りの動画を見て歌ったり、アマプラでM-1を第一回から見てお笑いの変遷を眺めたりしている。昨年のM-1の優勝者はミルクボーイだったが、彼らのコーンフレークのネタは衝撃的に面白かった。コーンフレークという単語を聞くだけで少し笑ってしまう。彼らはそんな意味付けを我々に与えたのだ。この衝撃は凄まじい。

今年の言葉で言えば、コーンフレークのほかに多目的トイレという言葉にも笑ってしまう。以前は何ともないニュートラルな言葉だったのに、何か言葉にとって普通じゃない体験が影響して、言葉の印象を変えてしまうことは多々ある。これは言葉に限った話ではなく、映像や物語、音楽だって同様だ。たとえば、ラヴェルという作曲家が書いたボレロという曲があるが、人によっては光が丘で恐竜のようなモンスターが登場する映画を思い出すかもしれないし、向日葵に囲まれてスネアを叩いている可愛らしい少女がジャケットのアルバムを思い出すかもしれない。そもそもバレエ曲なので、バレエだとかスケートだとかの演技が頭に浮かぶ人もいるかもしれない。知識や体験の有無で、感覚が変わる。世界観が変わる。

同じものを味わっていたって、見えている世界が違うわけだが、より豊かな経験で以て、味わう方が面白いと個人的には思う。そういう考え方をしているから、貪欲に知識の吸収し、積極的に未知の体験を求め、自己の世界観を耕している。一方で、そういった趣味や習慣の行動が全く無い人も多く見受けられる。趣味がNetflixYouTube、AmazonPrimeVideoといった動画サイトを垂れ流して見るだけという人が意外といる。自分を構成するものを受動的に摂取するだけとなってしまっているのだ。新しいものを自分で探索して消化することはエネルギーを要する。その営みに慣れていない人、余裕のない人や営みから得られる快感を期待できない人には難しいのだろう。いわゆる、コスパが悪いってやつだ。こんな風に外側から冷静に見れているようだけれど、一番恐れているのは、自分がそのように思うようになってしまうことだ。忙しさに追われて習慣が薄れたり余裕を失っていくうちに、そのような感性になってしまうのが怖い。

私たちはこの10年で地震や疫病といった天災に見舞われてきた。もちろん実害も多いが、価値観の変容といった影響も大きいように思う。どのように変化しているのか現在進行形で捉えられるわけではない。それでも、自分が良しとするものを丁寧に見極め、真にカルチベートされ、疫にも負けず、そういうものに私はなりたいにゃ。

計上されていないレコード部分も含めてRで集計したいときの覚書

【用途】

集計対象のデータレコードが0だった場合, 0と記録されていないことが多々ある. 0だった場合も含めて集計して平均を計算したいなんてことがある. そんなときのために, Rで前処理して0のレコードを作ってしまう方法の一つのメモ.
別のもっと楽な方法があるかもしれないので, もし知っている方がいれば教えてほしい. (公開後すぐに教えていただいた技を最後に追記しました)

【内容】

データのイメージは, ユーザーがいて, 衣食住の費用が記録されているというもの.
まず初めはレコードが0と記録されているケース. ライブラリ読み込みと模擬データセットの作成.

# Rやtidyverse周りのアップデートをまだサボっている
library(tidyverse)
df_clothes <- data.frame(
  breakdown = "clothes",
  user = c("A", "B", "C", "D"),
  expenditure = c(14, 3, 7, 0)
)

df_food <- data.frame(
  breakdown = "food",
  user = c("A", "B", "C", "D"),
  expenditure = c(2, 8, 6, 12)
)

df_rent <- data.frame(
  breakdown = "rent",
  user = c("A", "B", "C", "D"),
  expenditure = c(7, 12, 9, 8)
)

df_expenditure <- rbind.data.frame(df_clothes,
                                   df_food,
                                   df_rent)
df_expenditure
##    breakdown user expenditure
## 1    clothes    A          14
## 2    clothes    B           3
## 3    clothes    C           7
## 4    clothes    D           0
## 5       food    A           2
## 6       food    B           8
## 7       food    C           6
## 8       food    D          12
## 9       rent    A           7
## 10      rent    B          12
## 11      rent    C           9
## 12      rent    D           8

本当にやりたい集計はこのような形になる. 費用項目ごとに平均を出す.

df_expenditure %>% group_by(breakdown) %>% 
  summarise(N = n(),
            ave_expenditure = mean(expenditure))
## # A tibble: 3 x 3
##   breakdown     N ave_expenditure
##   <fct>     <int>           <dbl>
## 1 clothes       4               6
## 2 food          4               7
## 3 rent          4               9

しかし, レコードに0が記録されていないデータセットだった場合を考えたいので, そのようなデータセットを作成. この場合に上と同じ集計をすると違う結果が出てしまう.
つまり, clothesの集計が3人分で行われている. お金を使っている人の平均を出していることになる.

df_expenditure_nonzero <- df_expenditure %>% filter(expenditure!=0)

df_expenditure_nonzero %>% group_by(breakdown) %>% 
  summarise(N = n(),
            ave_expenditure = mean(expenditure))
## # A tibble: 3 x 3
##   breakdown     N ave_expenditure
##   <fct>     <int>           <dbl>
## 1 clothes       3               8
## 2 food          4               7
## 3 rent          4               9

この問題を回避するため, 一度wide型に変換してNAを作成して, long型に戻すことで計上されていない部分を確保する.

df_expenditure_nonzero %>% spread(key = breakdown, value = expenditure) %>% 
  gather(key = breakdown, value = expenditure, -user)
##    user breakdown expenditure
## 1     A   clothes          14
## 2     B   clothes           3
## 3     C   clothes           7
## 4     D   clothes          NA
## 5     A      food           2
## 6     B      food           8
## 7     C      food           6
## 8     D      food          12
## 9     A      rent           7
## 10    B      rent          12
## 11    C      rent           9
## 12    D      rent           8
# wideとlongの変換をgather&spreadではなくpivotで書く(練習とメモ目的)
#df_expenditure_nonzero %>% pivot_wider(names_from = breakdown, values_from = expenditure) %>% 
#  pivot_longer(-user, names_to = "breakdown", values_to = "expenditure")

long&wideの再変換を通して集計すると, 欲しかった結果が得られる.

# NA入りだと平均が計算されない
#df_expenditure_nonzero %>% spread(key = breakdown, value = expenditure) %>% 
#  gather(key = breakdown, value = expenditure, clothes,food,rent) %>% 
#  group_by(breakdown) %>% 
#  summarise(N = n(),
#            ave_expenditure = mean(expenditure))

# NAを0に置換して集計
df_expenditure_nonzero %>% spread(key = breakdown, value = expenditure) %>% 
  gather(key = breakdown, value = expenditure, clothes,food,rent) %>% 
  group_by(breakdown) %>% 
  replace_na(list(expenditure=0)) %>% 
  summarise(N = n(),
            ave_expenditure = mean(expenditure))
## # A tibble: 3 x 3
##   breakdown     N ave_expenditure
##   <chr>     <int>           <dbl>
## 1 clothes       4               6
## 2 food          4               7
## 3 rent          4               9

wideとlongの変換を挟まずにもっと楽にできないかと思っているので, 分かったらここに追記する予定.

【追記】

Twitterで教えていただきました. 

 

df_expenditure_nonzero %>%
  complete(user, breakdown,
           fill = list(expenditure=0)) %>% 
  group_by(breakdown) %>% 
  summarise(N = n(),
            ave_expenditure = mean(expenditure))
## # A tibble: 3 x 3
##   breakdown     N ave_expenditure
##   <fct>     <int>           <dbl>
## 1 clothes       4               6
## 2 food          4               7
## 3 rent          4               9
# summariseの引数.groupsを入れたケースのメモ
#df_expenditure_nonzero %>%
#  complete(user, breakdown,
#           fill = list(expenditure=0)) %>% 
#  group_by(breakdown) %>% 
#  summarise(N = n(),
#            ave_expenditure = mean(expenditure),
#            .groups = "drop") # .groupsは{dplyr}v1.0.0から使える余計なungroupを不要にできるぽい

無駄なlongとwide変換もNA置換もなくなりました. ありがとうございました!!

【記憶の検索キーワード】

0がない, 集計, 平均, NA置換, long型, wide型, tidyr, complete

 

ゴミ箱を飛び越えた先にある

リモートワーク主体の労働をかれこれ二ヶ月続けている。満員電車の通勤を回避できていることは大変素晴らしいことであるが、リモートワークに起因してストレスがかかっていることもある。PCのスクリーンや冷暖房といった職場の設備が無い分の効率低下もあるが、とりわけストレスフルなのは、仕事の共有時のコミュニケーションの情報量が格段に落ちていることだ。情報共有が基本的に画面上の文字情報に依存してしまうため、意思疎通に困ることが増えた。対面で相手の顔や声、仕草を感知しながら、理解できることがある。画面上の言葉だけでは、何が分かっていて何が分かってないのかを表現する言葉がまだ不足している。分かってなさを、言葉の滞りや表情の崩れ具合で伝えることもできない。社歴が短く、分からないことがまだまだ多い私にとって、この問題が重く感じられている(話は逸れるが、リモートで講義を受けている学生は、同じ空間にいる人がなにか便利そうなツールや面白そうなものごとやってるということを見かけるということが、「なにか」を知るきっかけになるわけで、そのきっかけが乏しいとますます乏しくなって辛いよなと思う)。

先日、ファッションモデルからソフトウエアエンジニアになった人のnote(https://note.com/d0iasm/n/n5b2b8b4891a1)を読んだ。この文章の一文の、「基礎知識がなければ自分の問題点をうまく表現することすらできないことに気付き、自分で理論を学ぶことにしました」というものにとても共感した。どういう言葉で質問すればいいのか、どういうキーワードで検索すればいいのか、今考えていることは分野全体においてどの位置を占めているのか、こういったことは基礎となる理論や枠組みを捉えていないと難しい。基盤のフレームワークから、気になる事柄の位置づけを知っていたり、調べたいことの調べるための言葉やその周辺を知っていたりしないと、新たに学んでいくのが大変になってしまう。基盤に加えて、世界に馴染まないと分からない空気感、前提知識、暗黙の了解というものもある。共有が難しい、世界に浸らないと分からないこともある(日本語の「は」と「が」の使い分けって相当日本語に馴染んでいれば分かると思うが、それを説明するのは難しい。これに似ているかもしれない。こういったことは、簡単に分かりやすく説明しろと言われても難しいものだ)。

上のnoteの一文が、書き手がエンジニアの世界に入ったときに感じた言葉であったように、こういったことは未知の分野に入ったときに起こりうる。私は今、医学薬学分野に入りたてなのだが、この分野の言葉に慣れ、枠組みを捉えるために日々奮闘している。分からないという状態に居続けるのはすごく辛い。コンフォートとは程遠い。ときに、光の届かない暗い海の底にいるような気分になる。辛いならわざわざやらなくてもいいというのも一理ある。分からないということを忘れてしまうこともできないわけではない。わざわざ海の底に潜り込まなくとも生きていくことはできるのだろうけど、だが、しかし、分からないという状態から分かるという状態になったときの快感を忘れられないのかもしれない。潜って潜って世界が拓けた明るい場所に出られたときの興奮の虜になっている中毒者なのかもしれない。もしくは、知らないことに対する恐怖から逃げようとしているのかもしれない。そんなトリツカレやオソレで以て、また深い海の底に飛び込んでいってしまうのかもしれない。

本当は、こんなことはわざわざ書かないつもりだった。一見すると軽々と物事を理解していく人も多くいるだろう(内実ともにそういう人もいるかもしれない)。そんな人が目立つものだから、こういうことを書くのは少し躊躇われる。しかし、そうでない人だっているだろう。苦しみながらも、理解の歓楽や恐怖に溺れて潜ってを繰り返す人もいるだろう。そんな人を意識して書いている(書いているからなんなんだという話ではあるけれど)。何かを知ることに対して苦しんでいることに対する言語化をしようと強く思い立ったきっかけは、バナナマンのラジオの、とあるフリートーク(https://youtu.be/36nOjZCS4H4)を聞いたからだ。知識、認知能力、学習能力は人によって、広さと深さにバラツキがある。このトークで話されている問題は程度の差はあれ、人間誰にだって関わってくる。押さえておくべき、当たり前のところ。教養という言葉で括られてしまう問題なのかもしれない(個人的には、教養とは、共有できる日常の空間を広げるものだと定義するのがいいと思っている)。何を知らなければいけないだとか、何を知らなくていいだとか、そんなものはきっとないのだけれど、ないとも言い切れない部分もある。どうやって言葉を紡いで締めていけばいいのかは分かっていない。まとまりのない文を連ねて、少し荒れた心情や思考をただここに書き留めておく。

メタアナリシスの変量効果モデルのDerSimonian-Lairdの方法の学習記録

【学習動機】

メタアナリシスの変量効果モデル(ランダム効果モデル, random effects model)で異質性つまり, 研究間の分散 \tau^2 を推定する方法としてよく使われるDerSimonian-Lairdの方法があるのだが, これが一目だとよく分からない. その周辺について, 少し調べてメモしていく.

【学習内容】

モデルのセッティング

メタアナリシスの変量効果モデル(random-effects model)では, K個の研究i の効果量(effect size)を \theta_iとし, この\theta_iは平均\theta, 分散\tau^2正規分布に従うとする(ここで, 正規分布を仮定しているが, 以下でモーメント法を使った\tau^2の推定量が出てくるが, これには分布形として正規分布に特定する必要はないはず. 平均と分散があれば十分なはず. 変量効果モデルが見えやすいから, ここでは特定している).

つまり,

 \hat{\theta_i} \sim N(\theta_i,\sigma_i^2) \\ \theta_i \sim N(\theta,\tau^2)

研究結果の統合によって\thetaを推定することがメタアナリシスの目的の一つであるのだが, その推定量は, 以下のように各研究の効果量の推定値をウェイトw_iで加重平均することで求められる.

 \hat{\theta}=\Sigma_{i=1}^{K}(w_i\hat{\theta_i})/\Sigma_{i=1}^{K}w_i

メタアナリシスでは研究間の異質性を評価することも重要であり, この変量効果モデルでは異質性は研究間の分散 \tau^2で表され, この推定量\hat{\tau^2}

\hat{\tau_{DL}}^2=max{(0, \frac{Q-(K-1)}{\Sigma_{i=1}^{K}w_i-(\Sigma_{i=1}^{K}w_i^2)/(\Sigma_{i=1}^{K}w_i)})}

ただし,  Q=\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\hat{\theta})^2

として推定できる.

ここまでで加重平均に使われるウェイト w_iについて特定していない. このウェイトによって手法が異なってくる. ウェイトを各研究の効果量の推定値の分散\hat{\sigma_i^2}の逆数を使って\hat{w_i}=\frac{1}{\hat{\sigma_i^2}}w_iに代入する手法がDerSimonian-Lairdの方法と呼ばれている. 他にもあるが, 現在よく使われているのはこの手法のようだ.

\hat{\theta_i}と独立である, \hat{\sigma_i^2}は真の分散\sigma_i^2の代用ができるという仮定が暗に置かれている.

本題

さて, 推定量\hat{\tau^2}があのような形になっているのか. 順を追って見ていく.

準備1

\hat{\theta_i}の期待値は

\begin{aligned} E[ \hat{\theta_i} | \theta_i ]=\theta_i \\ E[ \hat{\theta_i} ]=\theta \end{aligned}

\hat{\theta_i}の分散は

\begin{aligned} var( \hat{\theta_i} )=\sigma_i^2+\tau^2 \end{aligned}

準備2

\hat{\theta}=\Sigma_{i=1}^{K}(w_i\hat{\theta_i})/\Sigma_{i=1}^{K}w_i

\hat{\theta}の分散は

\begin{aligned} var( \hat{\theta} )=\frac{\Sigma_{i=1}^{K}w_i^2var(\hat{\theta_i})}{(\Sigma_{i=1}^{K}w_i)^2} \\\ =\frac{\Sigma_{i=1}^{K}w_i^2(\sigma_i^2+\tau^2)}{(\Sigma_{i=1}^{K}w_i)^2} \end{aligned}

 

準備3

統計量Qについて

\begin{aligned} Q = \Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\hat{\theta})^2 \\ = \Sigma_{i=1}^{K}w_i[(\hat{\theta_i}-\theta)-(\hat{\theta}-\theta)]^2 \\ =\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\theta)^2 - 2\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\theta)(\hat{\theta}-\theta)+\Sigma_{i=1}^{K}w_i(\hat{\theta}-\theta)^2 \\\ =\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\theta)^2 - 2(\hat{\theta}-\theta)\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\theta)+\Sigma_{i=1}^{K}w_i(\hat{\theta}-\theta)^2 \\ =\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\theta)^2 - 2(\hat{\theta}-\theta)(\hat{\theta}-\theta)\Sigma_{i=1}^{K}w_i+\Sigma_{i=1}^{K}w_i(\hat{\theta}-\theta)^2 \\ =\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\theta)^2 - (\hat{\theta}-\theta)^2\Sigma_{i=1}^{K}w_i \end{aligned}

準備4

統計量Qの期待値について

\begin{aligned} E[Q]=\Sigma_{i=1}^{K}E[w_i(\hat{\theta_i}-\hat{\theta})^2]\\ =\Sigma_{i=1}^{K}w_iE[(\hat{\theta_i}-\theta)^2] - E[(\hat{\theta}-\theta)^2]\Sigma_{i=1}^{K}w_i \\\ =\Sigma_{i=1}^{K}w_ivar(\hat{\theta_i}) - (\Sigma_{i=1}^{K}w_i)var(\hat{\theta}) \\\ =\Sigma_{i=1}^{K}w_i(\sigma_i^2+\tau^2) - (\Sigma_{i=1}^{K}w_i)\frac{\Sigma_{i=1}^{K}w_i^2(\sigma_i^2+\tau^2)}{(\Sigma_{i=1}^{K}w_i)^2} \\\ =\Sigma_{i=1}^{K}w_i(\sigma_i^2+\tau^2) - \frac{\Sigma_{i=1}^{K}w_i^2(\sigma_i^2+\tau^2)}{\Sigma_{i=1}^{K}w_i} \\\ =\tau^2(\Sigma_{i=1}^{K}w_i-\frac{\Sigma_{i=1}^{K}w_i^2}{\Sigma_{i=1}^{K}w_i})+(\Sigma_{i=1}^{K}w_i\sigma_i^2 - \frac{\Sigma_{i=1}^{K}w_i^2\sigma_i^2}{\Sigma_{i=1}^{K}w_i}) \end{aligned}

モーメント法

E[Q]\tau^2が出てくることでモーメント法を使って\tau^2を推定する動機が与えられる. (ここの説明が色々読んでみてもどれも簡素過ぎて分かりにくい気がする)

E[Q]=Q として, 推定値で置き換えていくと(ここ, 私の中でまだ完璧に理解できていない).,

 \hat{\tau}^2 = \frac{\Sigma_{i=1}^{K}w_i(\hat{\theta_i}-\hat{\theta})^2 - (\Sigma_{i=1}^{K}w_i\sigma_i^2 - \frac{\Sigma_{i=1}^{K}w_i^2\sigma_i^2}{\Sigma_{i=1}^{K}w_i})}{\Sigma_{i=1}^{K}w_i-\frac{\Sigma_{i=1}^{K}w_i^2}{\Sigma_{i=1}^{K}w_i}}

と推定量が得られる.

モーメント法によって得られた推定量だが, まだウェイトが特定されていない. ウェイトをw_i=1/\sigma_i^2とすると, DerSimonian-Lairdの方法による\tau^2の推定量が得られる. つまり,

 \hat{\tau}_{DL}^2 = \frac{Q - (K-1)}{\Sigma_{i=1}^{K}w_i-\frac{\Sigma_{i=1}^{K}w_i^2}{\Sigma_{i=1}^{K}w_i}}

ウェイトを別の量にして別の方法による推定量も得られる. つまり, DerSimonian-Lairdの方法による\tau^2の推定量はモーメント法によって得られた推定量の特殊ケースの一つなのである. 1ステップで反復計算不要なので手軽に得られる推定量なのでよく使われているが, 他にも推定量は多く提案されている(2ステップだったり, 反復計算ありだったり, そもそものモデルの枠組みがベイズの枠組みだったり). どの手法が良いのか, 数多くの研究が行われている. Veroniki et al.(2016)では, シミュレーション研究の結果から, PM(Paule and Mandel)の方法かREMLが推奨されている. イベントが滅多にない(rate)なケースや異質性が大きい(\tau^2が大きい)ケースはDerSimonian-Lairdの方法を使うのに注意が必要そう.

Higgins, Thompson and Spiegelhalter(2009)やLangan(2015)を読んでいると, 変量効果モデルでは 各研究内の分散\sigma_i^2は既知で各研究の推定値\hat{\sigma_i}^2で置き換えられるという仮定が暗黙に置かれていることが多いようだ(そうでなけれれば, \hat{\sigma_i}^2の不確実性も考慮しないといけなってもっとなるはず. この仮定が明示されていないせいで, 勉強していてとても混乱した)

【学習予定】

メタアナリシスに関する日本語文献は少なく, ネット上の情報の多くはメタアナリシスをやってみた程度のものしか見当たらないので, 日本語情報を充実させられたらと思っているので, また何か書いたら記事にしていこうと思う.

学習していた感想としては, いつもの変量効果モデルは観測値をモデル化するだけなのでデータの生成構造が明確なのでが, メタアナリシスの変量効果モデルは, 各研究の効果量を真の分布から生成するモデルを考えるわけだが, 各研究の中でのデータの生成は見ず, 要約された情報のみ観測されるため, データの生成構造が少し複雑になって難しいと感じた. 加重平均の議論も絡んでくるから分かりにくさが増える.

【参考文献】

・DerSimonian and Laird(1986)
“Meta-analysis in Clinical Trials”
https://pubmed.ncbi.nlm.nih.gov/3802833/
DL法の元論文.
“Random-effects model for meta-analysis of clinical trials: An update”というタイトルが2007年にDerSimonianとKackerによって書かれている.

・Borenstein, Rothstein, Hedges and Higgins(2009)
“Introduction to Meta-Analysis”
https://www.amazon.co.jp/dp/0470057246/ref=cm_sw_r_tw_dp_U_x_aoVVEbC468FHK
メタアナリシスの概要を把握したいならまずはこれか.

・丹後(2016)
『新版 メタ・アナリシス入門 ─エビデンスの統合をめざす統計手法─』 https://www.amazon.co.jp/dp/425412760X/ref=cm_sw_r_tw_dp_U_x_uvVVEbHAB8CCK メタアナリシスに関する数少ない日本語文献でありがたいのだが, 最初からこれだけで理解するには足りない気がする. まず概要を把握したいなら上のBorenstein, Rothstein, Hedges and Higgins(2009)から始めるといいと思う.

・Chen and Peace(2013)
“Applied Meta-Analysis with R”
https://www.amazon.co.jp/dp/1466505990/ref=cm_sw_r_tw_dp_U_x_LrVVEbPEFVNWE
Rのパッケージの使い方の前に, パッケージなしで計算の仕方を教えてくれるので良かった.
データは著者にメールしたらもらえる. Borenstein, Rothstein, Hedges and Higgins(2009)の次あたりに読んでみるといいかも.

・Schwarzer, Carpenter and Rücker(2015)
“Meta-Analysis with R”
https://www.amazon.co.jp/dp/3319214152/ref=cm_sw_r_tw_dp_U_x_cRVVEb6DJ0AF4

・Whitehead(2002)
“Meta-Analysis of Controlled Clinical Trials”
https://www.amazon.co.jp/dp/0471983705/ref=cm_sw_r_tw_dp_U_x_3tVVEb435EAZT
理解のヒントがあるかなと買ってみたけど, まだちゃんと読めてない.

・Langan(2015)
“Estimating the Heterogeneity Variance in a Random-Effects Meta-Analysis”
http://etheses.whiterose.ac.uk/13507/
博論ぽい. 変量効果モデルの異質性の分散の推定に関する論文で, このテーマに関して一番よくまとまっているように思う. 今回使ったのはVolume I.

・Higgins, Thompson and Spiegelhalter(2009)
“A re-evaluation of random-effects meta-analysis”
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2667312/
仮定とか整理されている

・超具体的至極簡単計算機番組作成指南講座
http://milkyway.sci.kagoshima-u.ac.jp/~kameno/MODELFIT/average_3.html
加重平均と誤差の話はこのへんが分かりやすいかも.

・Rukhin(2009)
“Weighted means statistics in interlaboratory studies”
https://www.semanticscholar.org/paper/Weighted-means-statistics-in-interlaboratory-Rukhin/088136d0bc86caf0fd8efe441272a40d782724db

・Cohrane(1952)
“The chi-square test of goodness of fit cochrane”
https://projecteuclid.org/euclid.aoms/1177729380
コクランの有名なやつ見つけたからメモ.

・Borenstein(2020)

"Research Note: In a meta-analysis, the I2 index does not tell us how much the effect size varies across studies"

https://www.sciencedirect.com/science/article/pii/S1836955320300163?via%3Dihub

今回は扱わなかった I^2 indexについてのリサーチノート.  “Introduction to Meta-Analysis”の著者の一人が書いてる. 偶然見かけて気になったのでここにメモ.

・Veroniki(2018)のスライド
“Methods to estimate the betweenstudy variance and to calculate uncertainty in the estimated overall effect size”
https://training.cochrane.org/sites/training.cochrane.org/files/public/uploads/resources/downloadable_resources/Methods%20to%20estimate%20the%20between-study%20variance%20and%20to%20calculate%20uncertainty%20in%20the%20estimated%20ove.pdf
分散推定の手法に関してまとまっているスライド. 2018年のものなので, 新しめの知見なはず. 手法の分類と性質を概観してくれて, 頭の整理が捗る.

・Veroniki et al. (2016)
“Methods to estimate the between-study variance and its uncertainty in meta-analysis”
https://onlinelibrary.wiley.com/doi/pdf/10.1002/jrsm.1164
上のスライドの元ネタ論文の一つ. 著者陣がメタアナリシスやネットワークメタアナリシスの論文でよく出てくるメンバーな気がする. メタアナリシスをやるなら, 必読論文な気がする. 2016年と割 と新しめの知見がまとまっているだろう. 2020年現在どうっているかまではまだ私は分かっていないが.

・長島先生の講義スライド

https://www.nshi.jp/contents/doc/meta/meta20191216.pdf

 

・自分の過去のブログ記事(2020)

moratoriamuo.hatenablog.com

 

 

メタアナリシスのリスク比統合のための人工データ生成の学習記録

  

【学習動機】

メタアナリシスの本や記事を読んでも, 実践例は全て過去のメタアナリシスの例をやるだけで, 人工データで手法が上手くいっていることの確認をしていることがほとんどない. 自分の頭の整理も兼ねて, これから気になったことを少しずつ試したり, 調べたりしていく. コードはRで書く. ここでは, パッケージの使い方の紹介などは基本的にはしないつもりだ.

今回は, 離散データのケース. 2*2の分割表のリスク比(効果量:Effect Size)を推定して統合する実験をする.

丹後『新版 メタ・アナリシス入門 ─エビデンスの統合をめざす統計手法─』のp75あたりを主に参考にしている. これを読みながら目を通すと分かりやすいかもしれない. 他にもメタアナリシスの本(和書はほとんどないので, だいたい洋書)を読んでいるところで, そのうち, どの本がどのような感じか書くつもりだ.

【学習内容】

パッケージの読み込みと乱数シードの決定.

library(tidyverse)
set.seed(55555)

2*2分割表データを固定効果モデルで生成(リスク比の推定)

まずは, 真のリスク比を設定し, 固定効果モデルを真のモデルとしてデータを生成して, 固定効果モデルでパラメータの推定をし, 均質性の検定を行う.

真のリスク比を0.8, 統合する研究数を10, 各研究のTreat群とControl群の人数を30,
Control群のイベント発生率は0.3, Treat群は0.3*0.8=0.24とする.
イメージとしては, 治療を行うとイベントが起きにくくなるということ.

ES_RR <- 0.8
Nstudy <- 10
nT <- nC <- 30
# Treat群とControl群のイベントの起こる確率
pC <- rep(0.3, Nstudy)
pT <- pC * ES_RR

各研究について, イベント数データを生成する.

# Treatment群のイベント数
XT <- rbinom(Nstudy, nT, prob = pT)
# Comparisonのイベント数
XC <- rbinom(Nstudy, nC, prob = pC)

df <- 
    data.frame(
      nT = nT,
      nC = nC,
      XT = XT,
      XC = XC
    )
df
##    nT nC XT XC
## 1  30 30 11 11
## 2  30 30  8 10
## 3  30 30  6 10
## 4  30 30 11 12
## 5  30 30  4 12
## 6  30 30  6  9
## 7  30 30  3 11
## 8  30 30  7  8
## 9  30 30  4  8
## 10 30 30  8  8

リスク比の推定値, 対数リスク比推定値, 標準誤差, 信頼区間, 固定効果モデルのときのウェイトを計算.

df <- 
  df %>% mutate(
    RR_hat = (XT*nC)/(XC*nT),
    LRR_hat = log(RR_hat),
    SE = sqrt((nT-XT)/(XT*nT) + (nC-XC)/(XC*nC)),
    CI_L = LRR_hat - 1.96*SE,
    CI_U = LRR_hat + 1.96*SE,
    w = 1/(SE^2)
  )
df %>% select(-nT, -nC)
##    XT XC    RR_hat     LRR_hat        SE       CI_L        CI_U        w
## 1  11 11 1.0000000  0.00000000 0.3393398 -0.6651061  0.66510605 8.684211
## 2   8 10 0.8000000 -0.22314355 0.3979112 -1.0030495  0.55676243 6.315789
## 3   6 10 0.6000000 -0.51082562 0.4472136 -1.3873643  0.36571302 5.000000
## 4  11 12 0.9166667 -0.08701138 0.3279874 -0.7298667  0.55584400 9.295775
## 5   4 12 0.3333333 -1.09861229 0.5163978 -2.1107519 -0.08647264 3.750000
## 6   6  9 0.6666667 -0.40546511 0.4594683 -1.3060230  0.49509274 4.736842
## 7   3 11 0.2727273 -1.29928298 0.5979764 -2.4713167 -0.12724927 2.796610
## 8   7  8 0.8750000 -0.13353139 0.4485426 -1.0126749  0.74561213 4.970414
## 9   4  8 0.5000000 -0.69314718 0.5552777 -1.7814915  0.39519713 3.243243
## 10  8  8 1.0000000  0.00000000 0.4281744 -0.8392219  0.83922186 5.454545

統合リスク比(固定効果モデルのあてはめ)と信頼区間を計算(pはpoolの意)

RRp <- exp(sum(df$w * df$LRR_hat)/sum(df$w))
RRp
## [1] 0.7261641
RRp_CI_L <- exp(log(RRp) - 1.96*sqrt(1/sum(df$w)))
RRp_CI_L
## [1] 0.5564975
RRp_CI_U <- exp(log(RRp) + 1.96*sqrt(1/sum(df$w)))
RRp_CI_U
## [1] 0.947559

異質性について調べるため, 均質性の検定を行う. 統計量Q1を計算.

Q1 <- sum(df$w * (df$LRR_hat - log(RRp))^2)
Q1
## [1] 7.808073

Q1は自由度が研究数-1のカイ二乗分布に従う.

1-pchisq(Q1, df=Nstudy-1)
## [1] 0.5535978

リスク比について有意性の検定を行う.

Q2 <- (log(RRp)^2*sum(df$w))
Q2
## [1] 5.554217
1-pchisq(Q2, df=1)
## [1] 0.01843621

いちおう、このケースで, 変量効果モデルのあてはめをDerSimonian-Lairdの方法で行い, 変量効果の分散の推定値を確認する. 0になっているはず.

tau2_hat <- max(0,(Q1-(Nstudy-1))/(sum(df$w)-(sum(df$w^2)/sum(df$w))))
tau2_hat
## [1] 0

2*2分割表データを変量効果モデルで生成(リスク比の推定)

次に,真のリスク比の従う正規分布を設定し, 変量効果モデルを真のモデルとしてデータを生成して, 固定効果モデルでパラメータの推定をし, 均質性の検定を行った後, 変量効果モデルをあてはめる.

真のリスク比の分布 N(0.8, 0.3^2)で, 各研究の真のリスク比はその分布に従って生成されているとする.

ES_RR_mu <- 0.8
ES_RR_tau <- 0.3
ES_RR_tau2 <- ES_RR_tau^2
Nstudy <- 10
nT <- nC <- 30

ES_RR <- rnorm(Nstudy, mean = ES_RR_mu, sd = ES_RR_tau)
pC <- 0.3
pT <- pC * ES_RR

各研究について, イベント数データを生成する.

# Treatment群のイベント数
XT <- rbinom(Nstudy, nT, prob = pT)
# Comparisonのイベント数
XC <- rbinom(Nstudy, nC, prob = pC)

df <- 
  data.frame(
    nT = nT,
    nC = nC,
    XT = XT,
    XC = XC
  )
df
##    nT nC XT XC
## 1  30 30  3 11
## 2  30 30  7 10
## 3  30 30  6  8
## 4  30 30  7 11
## 5  30 30  9  7
## 6  30 30  3  7
## 7  30 30  6  8
## 8  30 30 12  8
## 9  30 30  3 15
## 10 30 30  5  8

リスク比の推定値, 対数リスク比推定値, 標準誤差, 信頼区間, 固定効果モデルのときのウェイトを計算.

df <- 
  df %>% mutate(
    RR_hat = (XT*nC)/(XC*nT),
    LRR_hat = log(RR_hat),
    SE = sqrt((nT-XT)/(XT*nT) + (nC-XC)/(XC*nC)),
    CI_L = LRR_hat - 1.96*SE,
    CI_U = LRR_hat + 1.96*SE,
    w = 1/(SE^2)
  )
df %>% select(-nT, -nC)
##    XT XC    RR_hat    LRR_hat        SE       CI_L       CI_U        w
## 1   3 11 0.2727273 -1.2992830 0.5979764 -2.4713167 -0.1272493 2.796610
## 2   7 10 0.7000000 -0.3566749 0.4197505 -1.1793859  0.4660360 5.675676
## 3   6  8 0.7500000 -0.2876821 0.4743416 -1.2173917  0.6420276 4.444444
## 4   7 11 0.6363636 -0.4519851 0.4087781 -1.2531903  0.3492200 5.984456
## 5   9  7 1.2857143  0.2513144 0.4327835 -0.5969413  1.0995702 5.338983
## 6   3  7 0.4285714 -0.8472979 0.6399405 -2.1015812  0.4069855 2.441860
## 7   6  8 0.7500000 -0.2876821 0.4743416 -1.2173917  0.6420276 4.444444
## 8  12  8 1.5000000  0.4054651 0.3763863 -0.3322521  1.1431823 7.058824
## 9   3 15 0.2000000 -1.6094379 0.5773503 -2.7410444 -0.4778314 3.000000
## 10  5  8 0.6250000 -0.4700036 0.5082650 -1.4662031  0.5261958 3.870968

統合リスク比(固定効果モデルのあてはめ)と信頼区間を計算(pはpoolの意)

RRp <- exp(sum(df$w * df$LRR_hat)/sum(df$w))
RRp
## [1] 0.7099767
RRp_CI_L <- exp(log(RRp) - 1.96*sqrt(1/sum(df$w)))
RRp_CI_L
## [1] 0.5301898
RRp_CI_U <- exp(log(RRp) + 1.96*sqrt(1/sum(df$w)))
RRp_CI_U
## [1] 0.9507291

変量効果の分散(研究間のバラツキ, ES_RR_tau2)を推定するため, 統計量Q1を計算.

Q1 <- sum(df$w * (df$LRR_hat - log(RRp))^2)
Q1
## [1] 13.99194

検定の結果も見ておく.

1-pchisq(Q1, df=Nstudy-1) 
## [1] 0.1226122

変量効果の分散を推定.

tau2_hat <- max(0,(Q1-(Nstudy-1))/(sum(df$w)-(sum(df$w^2)/sum(df$w))))
tau2_hat
## [1] 0.1245095

変量効果の分散の真値は0.09であり, 近いところを推定しているだろうか.

異質性の尺度I2

I2 <- (Q1 - (Nstudy - 1))/Q1*100
I2
## [1] 35.67726

DerSimonian-Lairdの方法で使うウェイトを計算

df <- 
  df %>% mutate(
    w_RE = 1/(SE^2 + tau2_hat)
  )

統合リスク比(変量効果モデルのあてはめ)

RRp <- exp(sum(df$w_RE * df$LRR_hat)/sum(df$w_RE))
RRp
## [1] 0.6749969
RRp_CI_L <- exp(log(RRp) - 1.96*sqrt(1/sum(df$w_RE)))
RRp_CI_L
## [1] 0.4666199
RRp_CI_U <- exp(log(RRp) + 1.96*sqrt(1/sum(df$w_RE)))
RRp_CI_U
## [1] 0.9764281

有意性の検定

Q2 <- (log(RRp)^2*sum(df$w_RE))
Q2
## [1] 4.354061
1-pchisq(Q2, df=1)
## [1] 0.03692081

まとめ

人工データを作って実験してみた. 今回の例は一応, 上手くいっているが, 乱数シードを変えると, 変量効果モデルの分散が0と推定されてしまったり, 異質性がないと判断されてしまうことが多々あった.
変量効果と他の要素のバランスが重要なのかもしれない. 分散要素の比重だとは思うのだけれど, どのうようになるとどうのような結果が起きるかがまだよく分かっていない.

モデルを理解したと思ってコードを書いてはいるのだが, 正しく理解できているかまだ自信がない(メタアナリシスの数理モデルが明確に記述されている本があまり見当たらないため). 間違いに気付いたら書き換える予定だ.

【学習予定】

離散データならオッズ比のパターン, 連続データなら平均値の差のパターンあたりで人工データを作って実験するのもありかもしれない. もう少し色々実験していきたいところ.
変量効果モデルのDerSimonian-Lairdの方法で出てくる変量効果モデルの分散(研究間のバラツキ)の推定量が自明じゃない形をしていると思うので, そのうちどうやって導出するか書きたい. ベイズの枠組みでモデルをあてはめるケースもやってみたいところ.
あと, ネットワークメタアナリシスも.

 

落陽の鹿

志村が死んだ。今回はフジファブリックではない。志村けんだ。志村けんの死は世間に大きく響いたようだ。志村も死んだが、ワニも死んだ。それと同時にその評判も死んだ。評判の死因は色々な人が分析していた。簡単に言ってしまえば、PR会社の仕事がただ下手だった(https://anond.hatelabo.jp/20200327165602)に尽きると思う。良さを台無しにする施策の数々。自然な流れの中に不自然を無理やり埋め込む不調和。良さに浸ろうとしていたところに、急激に邪魔な情報が入り込んでくるとイラッとする。これに似たようなことは少し前に書いた(https://moratoriamuo.hatenablog.com/entry/2019/10/16/225005)。

この評判の急落騒動が起きてから全部読んだって人で、「全然面白くなかった」と言っている人もいたが、個人的には内容は悪くないよぅに思った。「100日後に死ぬ」という意外な発想、死ぬことだけが決まっているほのぼのとした日常描画の毎日投稿、確実にやってくる死の原因を想像させる空間。これらの条件が揃って、この作品の良さは発揮されていた。条件が揃わずに味わったってそれは感じるものも違うだろう。新鮮味が売りで良いとされたものは、新鮮味が失われれば良いと評価しにくくなるのも当然だろう。だからといって、それが良かったと評価されうるべきものだったことは無視するものではないように思う。

最近観たアニメで、映像研がとても面白かった。『映像研には手を出すな!』だ。「チェーンソーの振動が観たくて死にかかってる人がいるかもしれない。私はチェーンソーの刃が跳ねる様子を観たいし、そのこだわりで私は生き延びる。大半の人が細部を見なくても、私は私を救わなくちゃいけないんだ。」というセリフが熱かった。このアニメ(漫画原作の作品だが)を象徴していたように思える。細部に対して叫びたくなるほど熱烈にこだわりを持って、それを表現する人がいるのなら、そのこだわりに気付いて評価できる人間でありたいとも思った(そういえば、自分は人が熱烈に好きなものを語っているのを聞くのが好きなのかもしれない)。

先日は、春が来たというのに、桜咲く木に雪が降り積もった。寒いのはどうも苦手だ。陽炎立ち昇る、アイスクリームの美味しい夏の到来が待ち遠しいものだ。新型のウイルス騒動で人がたくさん死ぬのはもう辛い。災害の収束した夏を鶴首して待っている。