# 行列計算でクロス集計をする
## 前提
### やりたいこと
- クロス分析したい
- 下図参照
- その他
- 要件が決まってない
- 何でもできるように作ってしまおう!
### 作戦
[[ブラウザ上で複雑な集計を行いたい]]
👉 [[Rust + WebAssembly]] を試す
## 数式
### 生データ
3 人分の属性データ(性別、年代)
$
N = 3
$
$
\begin{pmatrix}
男性 & 女性 & 20 代 & 30 代 & 40 代
\end{pmatrix}
$
$
\mathrm{ATTR} =
\begin{pmatrix}
1 & 0 & 1 & 0 & 0 \\
0 & 1 & 1 & 0 & 0 \\
0 & 1 & 0 & 1 & 0
\end{pmatrix}
$
3 人分の回答データ(10 問)
$
\begin{pmatrix}
男性 \cdot 20 代 \\
女性 \cdot 20 代 \\
女性 \cdot 30 代
\end{pmatrix}
$
$
\mathrm{DATA} =
\begin{pmatrix}
1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 \\
5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 \\
3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 & 5 & 6
\end{pmatrix}
$
### クロス集計
- 20 代(性別は問わない) ... 条件数 1
- 20 代女性 ... 条件数 2
集計条件
$
\begin{aligned}
\mathrm{COND} &=
\begin{pmatrix}
0 & 0 & 1 & 0 & 0 \\
0 & 1 & 1 & 0 & 0
\end{pmatrix} \\
\\
\mathrm{COND\_COUNT}&=
\begin{pmatrix}
1 \\
2
\end{pmatrix}
\end{aligned}
$
活性化関数 (Rectified Linear Unit)
$
relu(x) =
max(0, x)
$
集計
$
\begin{aligned}
\mathrm{MASKBASE} &= \mathrm{COND} \times \mathrm{ATTR}^{\mathrm{T}} \\
&=
\begin{pmatrix}
1 & 1 & 0 \\
1 & 2 & 1
\end{pmatrix} \\
\\
\mathrm{MASKBASE}2 &= \mathrm{MASKBASE} - (\mathrm{COND\_COUNT} \times 1_{1 \times N}) + 1 \\
&= \mathrm{MASKBASE} -
\begin{pmatrix}
1 & 1 & 1 \\
2 & 2 & 2
\end{pmatrix} +
\begin{pmatrix}
1 & 1 & 1 \\
1 & 1 & 1
\end{pmatrix} \\
&=
\begin{pmatrix}
\begin{matrix}
1 & 1 & 0 \\
0 & 1 & 0
\end{matrix}
\end{pmatrix} \\
\\
\mathrm{MASK} &= relu(\mathrm{MASKBASE}2) \\
&=
\begin{pmatrix}
\begin{matrix}
1 & 1 & 0 \\
0 & 1 & 0
\end{matrix}
\end{pmatrix}
\end{aligned}
$
該当する人数
$
1_{1 \times N} \times \mathrm{MASK}^{\mathrm{T}} =
\begin{pmatrix}
2 & 1
\end{pmatrix}
$
- 20 代: 2 人
- 20 代女性: 1 人
該当する回答者のスコアの合計
$
\mathrm{MASK} \times \mathrm{DATA} =
\begin{pmatrix}
6 & 8 & 4 & 6 & 8 & 10 & 6 & 8 & 4 & 6 \\
5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 & 1 & 2
\end{pmatrix}
$
### 全ての属性の集計
全属性値
- 全体
- 男性
- 女性
- 20 代
- 30 代
- 40 代
$
\mathrm{ALLATTR} = \\
\begin{pmatrix}
1 & 1 & 1 & 1 & 1 \\
1 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 \\
0 & 0 & 0 & 0 & 1
\end{pmatrix}
$
集計
- $\mathrm{COND\_COUNT}$ も作っておけば、クロス集計と同じ計算ロジックになる
$
\begin{aligned}
\mathrm{MASKBASE} &= \mathrm{ALLATTR} \times \mathrm{ATTR}^{\mathrm{T}} \\
&= \begin{pmatrix}
2 & 2 & 2 \\
1 & 0 & 0 \\
0 & 1 & 1 \\
1 & 1 & 0 \\
0 & 0 & 1 \\
0 & 0 & 0
\end{pmatrix} \\
\mathrm{MASK} &=
\begin{pmatrix}
1 & 1 & 1 \\
1 & 0 & 0 \\
0 & 1 & 1 \\
1 & 1 & 0 \\
0 & 0 & 1 \\
0 & 0 & 0
\end{pmatrix}
\mathrm{}
\end{aligned}
$
該当する人数
$
1_{1 \times 3} \times \mathrm{MASK}^{\mathrm{T}} =
\begin{pmatrix}
3 & 1 & 2 & 2 & 1 & 0
\end{pmatrix}
$
- 全体: 3 人
- 男性: 1 人
- 女性: 2 人
- 20 代: 2 人
- 30 代: 1 人
- 40 代: 0 人
各属性のスコアの合計
$
\mathrm{MASK} \times \mathrm{DATA} =
\begin{pmatrix}
9 & 12 & 9 & 12 & 9 & 12 & 9 & 12 & 9 & 12 \\
1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 \\
8 & 10 & 6 & 8 & 4 & 6 & 8 & 10 & 6 & 8 \\
6 & 8 & 4 & 6 & 8 & 10 & 6 & 8 & 4 & 6 \\
3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0
\end{pmatrix}
$
### 平均
- スコア 0 を未回答とする
- 平均の分母から除外する
符号関数 (sign function, sugnum function)
$
sgn(x) =
\begin{cases}
1 & (x > 0) \\
0 & (x = 0) \\
-1 & (x < 0)
\end{cases}
$
$
\mathrm{VALID\_COUNT} = \mathrm{MASK} \times sgn(\mathrm{DATA})
$
ゼロ除算に注意して合計の各要素を $\mathrm{VALID\_COUNT}$ で割る。
## Rust 実装
- 行列計算できれば言語は何でもよい
- Rust だと環境が整っている
[[行列計算でクロス集計をする (Rust)]]
## WebAssembly
[[Rust + WebAssembly で行列計算]]