Julia(とR)で古典的多次元尺度法

昨日、こんなツイートを見た。

このデータは以前にも見たことがあって、多次元尺度法のよいサンプルになるかと思っていたのでした。今日はJuliaで古典的多次元尺度法をやってみる。

データは国土地理院都道府県庁間の距離からダウンロードが可能。Excelファイルを持ってくる。このデータは人間が読むにはいいんだけど、ソフトで解析しようとすると下三角行列だけだったり県名が変なところに付いていたりしてめんどくさい。以下のように変換してCSVファイルに保存した。手っ取り早かったのでRでやった。

library(readxl)

# Excelファイルの読み込み
rawdat <- read_excel("000195511.xlsx")

# Excelファイルには下三角行列にしかデータが入っていないので、対称な距離行列を作る
D <- matrix(0, nrow=47, ncol=47)
for (r in 1:46) {
  for (c in 1:r) {
    D[r+1, c] = as.numeric(rawdat[r+3, c+1])
    D[c, r+1] = as.numeric(rawdat[r+3, c+1])
  }
}

# 県名もとってくる
prefnames <- rbind(as.matrix(rawdat[3,2]), as.matrix(rawdat[4:49,1]))
for (n in 1: 47) {
  prefnames[n] <- gsub(" ", "", prefnames[n])
}
rownames(D) <- prefnames
colnames(D) <- prefnames

# CSVファイルに保存
write.csv(D, file="prefecture_distance.csv")

Rでやるなら、この続きで

X <- cmdscale(D)
plot(X, type="n", xlab="Dim. 1", ylab="Dim. 2", asp=1)
text(X, label=rownames(X))

とすると下のような図ができる。簡単だなー。

f:id:amarui:20191116134535p:plain
Rで作った多次元尺度法の図

ここからはJuliaで同じことをやってみる。まずは必要なパッケージの読み込み。多次元尺度法の関数はMultivariateStatsに入っている。

using CSV
using MultivariateStats
using Plots

先ほど作ったCSVファイルを読み込む。DataFrameの状態だと多次元尺度法の計算ができないので配列に変換している。

df = CSV.read("prefecture_distance.csv")
pref_names = df[!, :Column1]
pref_dist = df[:, 2:end]
pref_dist = convert(Matrix, pref_dist)

ここから古典的多次元尺度法の計算。

res = transform(fit(MDS, pref_dist, maxoutdim=2, distances=true))

プロットしてみる。

scatter(res[1,:], res[2,:], legend=false, aspect_ratio=1)

f:id:amarui:20191116143351p:plain
Juliaで作った多次元尺度法の図

日本語テキストがうまく入れられなかったので、ここまで。Rでやったのと(回転しているけど)同じ結果になっているので良しとする。