盆暗の学習記録

データサイエンス 、ソフトウェア開発、ビジネスについて日々学んだことの備忘録としていく予定です。初心者であり独学なので内容には誤りが含まれる可能性が大いにあります。

離散化された順序尺度のカテゴリカル変数同士の相関係数を測るライブラリ

を作ったので紹介させてください。

順序尺度とは

順序尺度 (ordinal-scale)というのは大小関係をもつカテゴリカル変数のことです。

例えば

  • アンケートで見かける 「あてはまる」「どちらでもない」「あてはまらない」のような該当度合いについての選択肢
  • 試験の答案データにおける 「正解」「不正解」のような、二値変数のうち順序性が考えられる変数

などを指します。

順序尺度の相関係数とは

なぜ積率相関係数ではだめなのか

順序尺度の変数はカテゴリカルな変数であるものの、その大小関係に応じた数値を割り振る(label encoding)ようにすれば計算が可能です。

単純な方法はピアソンの積率相関係数をそのまま適用する方法ですが、データの生成過程が「連続値をある閾値で切断して離散化している」となっているデータについては、その生成過程を考慮してモデリングした相関係数を用いたほうが推定を誤りにくいです。

離散化が仮定されるデータというのは、例えば数学のテストで二次関数への理解度を確認する意図で作られた設問への「正解」「不正解」という観測値があったとして、その背後には「二次関数への理解度」という連続的な値(実際には観測できない潜在変数)があり、ある閾値を越えたら「正解」が観測できる、というようなものです。

このようなデータについては ピアソンの積率相関係数をそのまま適用しても推定にバイアスが含まれることがあります 。例えば相関係数が0.5の2変量正規分布から疑似乱数を生成させたデータを離散化した変数に対してピアソンの積率相関係数を適用すると、カテゴリ数が少ないときはバイアスが大きいことがわかります。

(関連記事:https://nigimitama.hatenablog.jp/entry/2023/04/24/000000

ただしカテゴリ数が多ければピアソンの積率相関係数を使ってもバイアスが比較的小さくなるため、アンケートのリッカート尺度では5段階や7段階といったカテゴリ数がやや多めのものが使われます。

離散化された順序尺度の相関係数の例

そのような離散化された順序尺度に対する相関係数には以下のものがあります。二値変数だけが対象のものと多値へと一般化したものとで合計4つです。

名前 変数の型 前提
イシリアル(biserial)相関係数 二値 × 連続変数 2値変数は連続潜在変数を閾値で離散化
テトラコリック(tetrachoric)相関係数 二値 × 二値 両方の2値は連続潜在変数を閾値で離散化
ポリシリアル(polyserial)相関係数 多値 × 連続変数 順序変数は連続潜在変数を閾値で離散化
ポリコリック(polychoric)相関係数 多値 × 多値 両方の順序変数は連続潜在変数を閾値で離散化

(※名前が似ているpoint-biserialはピアソンの積率相関係数と等しいので別物です)

これらの手法の基本的な考え方は、観測されたカテゴリカル変数の背後にある潜在変数が標準正規分布に従うと仮定し、最尤推定して相関係数を求める というものです。

(詳細は 小杉考司(2013)「順序尺度の相関係数(ポリコリック相関係数)について」 などをご覧ください)

Pythonの既存ライブラリ

Pythonの一部の統計ライブラリ

では上記のような離散化された順序尺度に対する相関係数たちが実装されています。

しかし、残念ながら更新が止まってしまっており、現行バージョンのPythonでは動かなかったりします。 (semopyはプルリクを出せばマージだけしてもらえたりするので後でプルリクを出してみようかと思っていますが)

相関係数だけのシンプルで、更新がとまっていないライブラリがほしい…!となったため、自作することにしました。

作ったライブラリ

こちらになります

github.com

マニアックな相関係数を扱う関係上ほぼニーズはないと思いますが、興味のある方はぜひご利用ください

(わたしは本業の仕事上たまたま離散化した順序尺度を扱う機会が出てきたため自分用に作ってます)

使い方

PyPIに公開しているためpipインストールできます。

pip install ordinalcorr

相関係数の名前通りの関数名(polychoric, polyserialなど)で実装してありますのでこんなふうに呼び出してください。

>>> from ordinalcorr import polychoric
>>> x = [1, 1, 2, 2, 3, 3]
>>> y = [0, 0, 0, 1, 1, 1]
>>> polychoric(x, y)
0.9986287922435596