Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mike-neck/85160685908f3c3204bbb8086b36c16c to your computer and use it in GitHub Desktop.
Save mike-neck/85160685908f3c3204bbb8086b36c16c to your computer and use it in GitHub Desktop.

コロナウィルスとか

以下では、コロナウィルスのニュースやツイートに出てくる数値を元に、感染予防対策のモデルを作成し、どのような施策がどういう結果をもたらすのかを見ていくことにする。

最初はウィルスに感染しているかどうかを判定する PCR 検査についてモデルを作っていく。

検査

検査を実施した場合、被験者の実際の感染有無と検査の判定の組み合わせで以下の 4 つのグループに分かれる。なお、「陽性」とは感染しているもの、「陰性」とは感染していないもののことを意味する。

- 検査の結果が陽性 検査の結果が陰性
被験者は感染 a b
被験者は未感染 c d

このとき、

  • 「感度」とは 感染している人が陽性として検出される割合 (a / (a + b))
  • 「特異度」とは 感染していない人が陰性として検出される割合 (d / (c + d))
  • 「偽陰性」とは 感染している人が陰性として検出される割合 (b / (a + b))
  • 「偽陽性」とは 感染していない人が陽性として検出される割合 (c / (c + d))

となる。

検査の精度

  • PCR 検査の精度は感度 0.4 、特異度 0.9 と言われている(twitter より)
  • また、 こちら の記事では感度が 0.3 〜 0.5 あるいは 0.7 となっている
  • 鼻から採取した検体で検査すると感度が向上するらしいが、医療者が自身のリスクをとって鼻よりも感度の下がる喉から採取した検体を使う傾向があり、検査の感度が下がる傾向にあるとのこと
  • また、感度を上げると特異度が下がるという性質があるらしい(参考)
  • PCR検査が容易になると医療者が接する人の数が増えて、感染を避けるために鼻でなく喉でやるようなケースが増えるかもしれない
    • あるいは医療関係者が感染して、検査を継続できなくなるケースも発生しうる

シミュレーションコード

ここでは上記の条件に基づき、検査のシミュレーションをおこなう。

確率

まずは確率を表すクラスを作る。

data class RationalProbability(
    val numerator: Int,
    val denominator: Int
) {
  fun inverse(): RationalProbability = 
      RationalProbability(denominator - numerator, denominator)

  fun runTest(): Boolean =
      ThreadLocalRandom.current().nextInt(denominator) < numerator

  companion object {
    fun create(num: Int, denom: Int): RationalProbability? =
        if (denom < num) null
        else if (num < 0 || denom < 0) null
        else RationalProbability(num, denom)
  }
}

Double などの値を用いても良さそうではあるが、感度 <--> 偽陽性の変換を安全に行える(inverse)ように有理数で表現する。

実際にテストで検出されるかどうかをシミュレートするための関数である runTest 関数を設けている。

なお、このクラスはコンパニオンオブジェクトにファクトリーメソッドを用意して、不適切な値(numeratordenomenator より大きい等)になるのを防ぐ。

PCR 検査

PCR 検査を表すクラスを作っていく。

先程記したとおり、検査には感度と特異度という 2 つのパラメーターがあるので、それをそのまま先程の確率クラスで表現する。

なお、感度を上げると特異度が下がるという性質があるらしいが、その関係性についてはここでは所与のものとして扱う(関心はない)。

data class PcrTest (
    val sensitivity: RationalProbability,
    val specificity: RationalProbability
) {
  companion object {
    fun create(sensitivity: RationalProbability?, specificity: RationalProbability?): PcrTest? =
        if (sensitivity != null && specificity != null) PcrTest(sensitivity, specificity)
        else null
  }
}

こちらにもファクトリーメソッドを用意した。これは Probability の計算失敗を吸収するようになっている。

@mike-neck
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment