裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

Julia で「クロンバックの α」

2021年10月01日 | ブログラミング

クロンバックの α,標準化されたクロンバックの α,Kuder-Richardson の方法についても述べる。

1. クロンバックの α

順序尺度変数やリッカート法により得られる回答データにも対応しているので,後述する "Kuder-Richardson の式 20" より優れている。

1.1. 定義

  • k:質問項目数
  • xj:質問j への回答
  • t:回答の合計 t = sum(x)
  • cov(xi, xj):質問i への回答と質問j への回答の不偏共分散
  • var(xi), var(t):質問iへの回答,回答の合計の不偏分散

https://www.real-statistics.com/reliability/internal-consistency-reliability/cronbachs-alpha/cronbachs-alpha-basic-concepts/
Cronbach’s Alpha Basic Concepts

1.2. 計算例

  data = [1 1 1 1 1 1 1 1 1 1 1
          1 1 1 1 1 1 1 1 0 1 0
          1 0 1 1 1 1 1 1 1 0 0
          1 1 1 0 1 1 0 1 1 0 0
          1 1 1 1 1 0 0 0 1 0 0
          0 1 1 0 1 1 1 1 0 0 0
          1 1 1 1 0 0 1 0 0 0 0
          1 1 1 1 1 0 0 0 0 0 0
          0 1 0 1 1 0 0 0 0 1 0
          1 0 0 1 0 1 0 0 0 0 0
          1 1 1 0 0 0 0 0 0 0 0
          1 0 0 1 0 0 0 0 0 0 0];
  k = size(data, 2)
  11
  t = sum(data, dims=2)
  12×1 Matrix{Int64}:
   11
    9
    8
    7
    6
    6
    5
    5
    4
    3
    3
    2
  varx = var(data, dims=1) # 不偏分散でも分散でも,以下と統一していればどちらでも可
  1×11 Matrix{Float64}:
   0.151515  0.204545  0.204545  0.204545  …  0.242424  0.204545  0.0833333
  Σvarx = sum(varx)
  2.3409090909090913
  vart = var(t) # 不偏分散でも分散でも,上と統一していればどちらでも可
  7.113636363636363
  α = k / (k-1) * (1 - Σvarx / vart)
  0.7380191693290735

1.3. Julia の関数として定義

  using LinearAlgebra, Statistics
  function alpha0(x)
      k = size(x, 2)
      VarCovMat = cov(x)
      Sy2 = sum(VarCovMat)
      Sj2 = sum(diag(VarCovMat))
      k / (k - 1) * (1 - Sj2 / Sy2)
  end
  alpha0 (generic function with 1 method)

上式の 2 番目の式を関数化する。

  using Statistics
  function alpha(x)
      k = size(x, 2)
      varx = var(x, dims=1)
      y = sum(x, dims=2)
      k / (k - 1) * (1 - sum(varx) / var(y))
  end
  alpha (generic function with 1 method)

1.4. 計算例

  alpha0(data)
  0.7380191693290735
  alpha(data)
  0.7380191693290735

以下のデータは 3 件法での回答を求めたものである。

  data2 = [1 1 1
           2 1 1
           2 1 2
           3 2 1
           2 3 2
           2 3 3
           3 2 3
           3 3 3
           2 3 2
           3 3 3];
  alpha0(data2)
  0.7734375
  alpha(data2)
  0.7734375000000003

ちなみに,R では,psych::alpha で計算できる。

  using RCall
  R"""
  library(psych)
  results = alpha($(data2))
  options(digits=16)
  print(results$total$raw_alpha)
  """;
  [1] 0.7734375

なお,psych::alpha( ) は相関係数を与えるオプションもあるが,粗データを与えた場合と結果が違う。

  using RCall
  R"""
  library(psych)
  results2 = alpha(cor($(data2)))
  options(digits=16)
  print(results2$total$raw_alpha)
  """;
  [1] 0.7742910373931703

オンラインヘルプを見ると,

When calculated from the item variances and total test variance, as is done here, raw alpha is sensitive to differences in the item variances. Standardized alpha is based upon the correlations rather than the covariances.

というくだりがある。つまり,変数(質問への回答)を標準化する方がよいとのことである。そこで,元データを標準化して alpha( ) に与えてやると確かに同じ値になる。

  using RCall
  R"""
  library(psych)
  scaled = scale($(data2))
  results2 = alpha(scaled)
  options(digits=16)
  print(results2$total$raw_alpha)
  """;
  [1] 0.7742910373931704

1.5. 相関係数を与えて標準化されたクロンバックの α を求める

https://towardsdatascience.com/cronbachs-alpha-theory-and-application-in-python-d2915dd63586
Cronbach’s Alpha: Theory and Application in Python

1.6. 定義

  • k:質問項目数
  • r:質問項目間の相関係数の平均値(相関係数行列の対角要素を含まない上三角行列の相関係数 r(i, j), i < j の平均値)

注意:元の Web ページのどこにも書いていないが,αst と記述されている点に注意。つまり「標準化されたクロンバックのα)の意なのだ。

Web ページには Python での関数が示されている。

  def cronbach_alpha(df):
      # 1. Transform the df into a correlation matrix
      df_corr = df.corr()

      # 2.1 Calculate N
      # The number of variables equals the number of columns in the df
      N = df.shape[1]

      # 2.2 Calculate R
      # For this, we'll loop through the columns and append every
      # relevant correlation to an array calles "r_s". Then, we'll
      # calculate the mean of "r_s"
      rs = np.array([])
      for i, col in enumerate(df_corr.columns):
          sum_ = df_corr[col][i+1:].values
          rs = np.append(sum_, rs)
      mean_r = np.mean(rs)

      # 3. Use the formula to calculate Cronbach's Alpha 
      cronbach_alpha = (N * mean_r) / (1 + (N - 1) * mean_r)
      return cronbach_alpha

これを Julia に書き換える。

  using Statistics
  
  function cronbach_alpha(df)
      # 1. Transform the df into a correlation matrix
      r = cor(df)
  
      # 2.1 Calculate N
      # The number of variables equals the number of columns in the df
      N = size(df, 2)
  
      # 2.2 Calculate R
      # For this, we'll loop through the columns and append every
      # relevant correlation to an array calles "r_s". Then, we'll
      # calculate the mean of "r_s"
      r_s = []
      for i = 1:N-1
          for j = i+1:N
              append!(r_s, r[i, j])
          end
      end
      mean_r = mean(r_s)
  
      # 3. Use the formula to calculate Cronbach's Alpha 
      (N * mean_r) / (1 + (N - 1) * mean_r)
  end
  cronbach_alpha (generic function with 1 method)
  cronbach_alpha(data2)
  0.7742910373931706

確かに,psych::alpha( ) の結果と一致した。

標準化というのは全ての変数の分散を同じにする(全ての変数を同格に扱う)ということである。
普通にクロンバックの α が使われる状況は,質問項目の回答の分散が大きく変わることはない(ほとんどの質問項目は 5 件法,ある項目は 0 ~ 100 の満足度などというのはあり得ない)。
なので,標準化されたクロンバックの α も,通常のクロンバックの α もほとんど同じ値になるだろう。
クロンバックの α の応用法として,ある質問項目を除いたら α がどれぐらい変化するかを検討することがある。この場合に使うのは標準化されないクロンバックの α である。

ということで,伝統的な(標準化しない)クロンバックの α を使う方がよいだろう。

2. Kuder and Richardson Formula 20

質問項目への回答が二値データ(たとえば 0/1)の場合には,"Kuder-Richardson の式 20"  を適用することができ,クロンバックの α と全く同じ結果が得られる。

2.1. 定義

  • k:質問項目数
  • pj:質問j に正解であった回答者数
  • qj:質問j に不正解であった回答者数
  • σ²:回答者ごとの得点(正解数)の分散(不偏分散ではない)

ρKR20 は 0 ~ 1 の範囲の値をとり,値が大きいことは信頼性があることを示す。しかし,あまりにも大きい数値(たとえば 0.9 以上)の場合は,質問紙が均質である(悪い意味で「それぞれの質問はほとんど同じ」)ことを示す。

https://www.real-statistics.com/reliability/internal-consistency-reliability/kuder-richardson-formula-20/
Kuder and Richardson Formula 20

2.2. 計算例

  n, k = size(data)
  (12, 11)
  p = sum(data, dims=1) ./ n
  1×11 Matrix{Float64}:
   0.833333  0.75  0.75  0.75  0.666667  …  0.416667  0.333333  0.25  0.0833333
  q = 1 .- p
  1×11 Matrix{Float64}:
   0.166667  0.25  0.25  0.25  0.333333  …  0.583333  0.666667  0.75  0.916667
  pq = p .* q
  1×11 Matrix{Float64}:
   0.138889  0.1875  0.1875  0.1875  0.222222  …  0.222222  0.1875  0.0763889
  Σpq = sum(pq)
  2.1458333333333335
  using Statistics
  σ² = var(totalscores, corrected=false) # 注:不偏分散ではない
  6.520833333333333
  ρKR20 = (1 - Σpq / σ²) * k / (k - 1)
  0.7380191693290734

2.3. Julia の関数として定義

  using Statistics
  
  function KR20(x)
  n, k = size(x)
  p = sum(data, dims=1) ./ n
  q = 1 .- p
  pq = p .* q
  Σpq = sum(pq)
  σ² = var(totalscores, corrected=false)
  (1 - Σpq / σ²) * k / (k - 1)
  end
  KR20 (generic function with 1 method)

前節の計算例のような 0/1 回答のデータに対して計算される "Kuder-Richardson の式 20" は,クロンバックの α と全く同じである。

  alpha0(data)
  0.7380191693290735
  alpha(data)
  0.7380191693290735
  KR20(data)
  0.7380191693290734
  
コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« Julia (VegaLite) で欠損値の... | トップ | Julia バージョンアップ v1.6... »
最新の画像もっと見る

コメントを投稿

ブログラミング」カテゴリの最新記事