top of page

Tableau実践問題集 #TableauChallenge を作りました。

R-Tableau勉強記5:Tableauで標本サイズが異なる場合のone-way ANOVAを実装する

前回の記事では標本サイズが同一の場合の対応なしone-way ANOVAの実装方法について書きました。

一方、実際にはデータに欠損値はつきもので標本サイズはグループごとに異なることは容易に発生し、かつTableau上にデータを読み込んだ段階では欠損値処理が難しかったりします。

Tableauに読み込ませる前に欠損値処理をしたデータを用意することも手ですが、BIツールの性質上、何らかの情報が集約されたデータを元に多種多様な分析や可視化をすることが多く、統計分析のために個別のデータソースを作成することはそこまで現実的でないかもしれません。


というわけで、今回はそのような欠損値を含むような集計データに対してのone-way ANOVAの実装を取り上げます。


参考:Rで分散分析 (p.48 ~ p.50)


今回使用したWorkbookは以下からダウンロードできます。

 

欠損値つきのデータに対する勧化方

今回は以下のようなデータを用意しました。

















良い感じに穴あきのデータであり、かく要因におけるデータ点数(標本数)がバラバラになっています。


ところで前回の復習ですが、各要素と全体平均値の差の総和は、以下のように「要因内の平均値の全体平均値に対するばらつき」と「各データの要因内の平均値に対するばらつき」に分解することができました。











標本数が同じの場合は、第1項は標本数nに平均値差の2乗和をかけたもので良かったのですが、今回の場合は標本数nはj番目要因によって変化するので、式が若干変わります。











この二つの項を使用してF値を計算するわけですので、それぞれをつらつら計算していく必要が出てきます。

ということで、まずはRコードを使用したTableau計算フィールドを以下に記載します。


p-value

SCRIPT_REAL(
"
#initial setup
library(installr)
key = .arg1
x = .arg2
g = .arg3

nc = length(unique(g))
unique_key = unique(key)
nr = length(unique_key)
label = factor(unique(g))

# align data with missing value label
x_matrix = matrix(NA, nrow=nr, ncol=nc)
for (i in 1:nr){
  for (j in 1:nc){
    if (!is.empty(x[key == unique_key[i] & g == label[j]])){
      x_matrix[i,j] = x[key == unique_key[i] & g == label[j]]  
    }
  }
}

m = ncol(x_matrix)
mx = nj = rep(0,m)

for (j in 1:m){
  xj = x_matrix[,j]
  nj[j] = length(xj[!is.na(xj)]) #sample size of each group
  mx[j] = mean(xj[!is.na(xj)]) #mean of each group
}

# variations
gmx = sum(mx*nj) / sum(nj) #total mean
ss_b = sum((mx - gmx)^2 * nj) #mean diff between mean of groups and total mean
ss_t = sum((c(x_matrix)[!is.na(c(x_matrix))] - gmx)^2)
ss_e = ss_t - ss_b

# degree of freedom
df_b = m-1
df_e = sum(nj) - m

# mean squares
ms_b = ss_b/df_b
ms_e = ss_e/df_e

# F value
f = ms_b/ms_e
p = 1 - pf(f, df_b, df_e)
"
,MIN([Order Date]), SUM([Sales]), MIN([Segment])
)

ここからコードの解説をしていきます。

library(installr)

まず事前準備として、is.empty()関数が欲しかったのでinstallrパッケージをダウンロードします。

key = .arg1
x = .arg2
g = .arg3

nc = length(unique(g))
unique_key = unique(key)
nr = length(unique_key)
label = factor(unique(g))

TableauからRに渡す際にはデータがベクトルとして入るのですが、そのベクトルから最終的には以下の形を作成したいとします。

















keyに指定するのは上記の行を指定するもの、xには各数値、gにはANOVAに要因として使用するディメンションを指定します。

ncは列数、nrは行数を取得しており、unique_key, labelは行と列のユニーク値を取得しています。

# align data with missing value label
x_matrix = matrix(NA, nrow=nr, ncol=nc)
for (i in 1:nr){
  for (j in 1:nc){
    if (!is.empty(x[key == unique_key[i] & g == label[j]])){
      x_matrix[i,j] = x[key == unique_key[i] & g == label[j]]  
    }
  }
}

ここではベクトル→行列の形に変換させるための処理を実施しています。

この処理により上図の表の形のデータがベクトルから作成されます。


あとはもう流れ作業で、F値の定義に従って必要な計算を行い、最後にpf()から算出されたF値のp値を求めています。

m = ncol(x_matrix)
mx = nj = rep(0,m)

for (j in 1:m){
  xj = x_matrix[,j]
  nj[j] = length(xj[!is.na(xj)]) #sample size of each group
  mx[j] = mean(xj[!is.na(xj)]) #mean of each group
}

# variations
gmx = sum(mx*nj) / sum(nj) #total mean
ss_b = sum((mx - gmx)^2 * nj) #mean diff between mean of groups and total mean
ss_t = sum((c(x_matrix)[!is.na(c(x_matrix))] - gmx)^2)
ss_e = ss_t - ss_b

# degree of freedom
df_b = m-1
df_e = sum(nj) - m

# mean squares
ms_b = ss_b/df_b
ms_e = ss_e/df_e

# F value
f = ms_b/ms_e
p = 1 - pf(f, df_b, df_e)

ということで、以下に前回のようなプロット図を出してみました。


ANOVA Label

IF [p-value] < 0.05

THEN '★'

ELSE ''

END


表計算の設定は以下です。





















ということで、標本数が異なる場合の対応なしone-way ANOVAもTableau上で実装することが出来ました。

 

最後に

今回は標本数が異なる場合の対応なしone-way ANOVAの実装方法について書きました。

Tableauへの実装は基本的にコードのコピー&ペーストで済んでしまうので、ぜひご自身の分析ダッシュボードに機会があれば使用してみてください。


ご質問等はTwitter、Linkedinへよろしくお願いします。それでは。

bottom of page