次のダーティデータ(仮想確率データ)に 含まれる異常値を可視化しながら見つける。
set.seed(1) # 乱数シード
n <- 100000 # データサイズ
# 正常値
rv <- runif(n = n, min = 0, max = 1) # 一様乱数
# 異常値1(負の値)
size <- 3 # ランダムサンプルサイズ
ii <- sample(n, size) # インデックスランダムサンプル
rv[ii] <- runif(n = size, min = -1, max = 0)
# 異常値2(とても大きな/小さな値)
rv[39] <- 22
rv[52] <- -21
rv[91] <- 11
# 小数点第2位に丸め行列(列数:100)に変換
m <- matrix(round(rv, 2), ncol = 100)
write.csv(as.data.frame(m),
file = 'data_cleansing2_dirty_data.csv',
row.names = F, quote = F)
# CSVデータを行列オブジェクトに変換
d <- read.csv(file = 'https://stats.dip.jp/01_ds/data/data_cleansing2_dirty_data.csv')
# Rのboxplot関数は行列(matrix)を引数とするのでデータフレームを行列に変換する。
m <- as.matrix(d)
boxplot(m)
any(m < 0) # 負のデータが存在
## [1] TRUE
any(abs(m) > 3*sd(m)) # 3シグマ(標準偏差の3倍)を超えるデータが存在
## [1] TRUE
jj <- 36:46
boxplot(m[, jj])
# 異常値が入っているカラム(列)の棒グラフを作成
j <- 37
y <- m[, j]
barplot(height = y, # 棒グラフの高さ
names.arg = 1:nrow(m)) # 横軸名
ii <- 140:231
y <- m[ii, j]
barplot(height = y, # 棒グラフの高さ
cex.names = 0.4, # 横軸ラベルの大きさ
names.arg = paste(ii, '\n(', y, ')')) # 横軸名 \nで改行して値も()内に表示
# さらにレコード(行)の範囲を絞り特定する。
ii <- 194:206
y <- m[ii, j]
barplot(height = y, # 棒グラフの高さ
cex.names = 0.4, # 横軸ラベルの大きさ
names.arg = paste(ii, '\n(', y, ')')) # 横軸名 \nで改行して値も表示
# 異常値を特定
m[200, j]
## V37
## -0.78
# 負の値
m[m < 0]
## [1] -21.00 -0.78 -0.99 -0.68
# 3シグマ(標準偏差の3倍)を超える値
sigma <- sd(m) # 標準偏差
#m[abs(m) > 3*sigma] # 数が多いためコメントアウトした。
# 4シグマ(標準偏差の4倍)を超える値
m[abs(m) > 4*sigma]
## [1] 22 -21 11
# 行と列のインデックス(Row, Col)と値(Value)のデータを作成
m.a <- NULL # 結果格納用の空のオブジェクトを作成
for (j in 1:ncol(m))
{
for (i in 1:nrow(m))
{ # 負値または4シグマを超える異常値を検出しレコードを追加していく。
if ( m[i, j] < 0 | m[i, j] > 4 * sigma )
{
cat('Row:', i, ', Col:', j, ', Value: ', m[i, j], fill = T)
m.a <- rbind(m.a, t(c(i, j, m[i, j]))) # rbind:行ベクトルを追加
}
}
}
## Row: 39 , Col: 1 , Value: 22
## Row: 52 , Col: 1 , Value: -21
## Row: 91 , Col: 1 , Value: 11
## Row: 200 , Col: 37 , Value: -0.78
## Row: 521 , Col: 59 , Value: -0.99
## Row: 242 , Col: 100 , Value: -0.68
# 結果表示
colnames(m.a) <- c('Row', 'Col', 'Value')
m.a
## Row Col Value
## [1,] 39 1 22.00
## [2,] 52 1 -21.00
## [3,] 91 1 11.00
## [4,] 200 37 -0.78
## [5,] 521 59 -0.99
## [6,] 242 100 -0.68
次のダーティデータ(仮想確率データ)から, 可視化する方法とそうでない方法で異常値を発見せよ。
d <- read.csv(file = 'https://stats.dip.jp/01_ds/data/data_cleansing2_dirty_data_exercise.csv')
library(DT)
## Warning: パッケージ 'DT' はバージョン 4.3.3 の R の下で造られました
datatable(d)