Sebelum bisa mengolah data di R, tentunya kita harus import file csv yang ingin kita olah. Selain itu kita juga harus import library agar kita bisa menggunakan fungsi-fungsi dari library tersebut yang akan memudahkan kita dalam mengolah data.
Untuk bisa import data csv, kita harus set working directory nya terlebih dahulu agar R tahu kita akan import file kita dari mana.
Library yang akan kita gunakan adalah factoextra dan outliers.
Selanjutnya kita menggunakan fungsi read.csv untuk membaca/membuka file 2019.csv di R. Lalu data tersebut akan disimpan sebagai variabel df. Kemudian kita menggunakan fungsi subset untuk memilih atribut yang akan kita gunakan. Dalam hal ini kita tidak akan menggunakan atribut overall.rank, Country, dan region karena merupakan data non numerik. (kita hanya akan menggunakan data numerik)
Sumber Data: https://www.kaggle.com/datasets/unsdsn/world-happiness/
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.3.2
## Loading required package: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(outliers)
setwd("D:/SEMESTER GANJIL 2023/Eksplorasi dan Visualisasi Data/Outlier")
df <- read.csv("2019.csv")
df <- subset(df,select = -c(Overall.rank,Country.or.region))
Kita akan mencoba terlebih graphical approach untuk mendeteksi outlier. Di sini kita menggunakan boxplot. Variabel df ada 7 atribut, oleh karena itu kita akan menggunakan looping agar bisa mencetak 7 boxplot yaitu 1 boxplot bagi masing-masing atribut. Fungsi par disini akan mengatur bahwa pada setiap page/slide akan memiliki maksimal 2 plot ke bawah (row 2 plot) dan 2 plot ke samping (column 2 plot).
#Graphical Boxplot Test
par(mfrow=c(2,2))
for(i in 1:7) {boxplot(df[,i], main=names(df)[i])}
Pada visualisasi yang diperoleh terlihat bahwa atribut yang memiliki outlier yaitu Social.support; Healthy.life.expectancy; Freedom.to.make.life.choices; Generosity; Perception.of.corruption.
Setelah mencoba mendeteksi outlier dengan graphical approach, kita akan menerapkan statistical approach. Di sini kita menggunakan Grubbs’ Test. Hal ini dilakukan dengan fungsi grubbs.test pada df. Variabel df ada 7 atribut, oleh karena itu kita akan menggunakan fungsi sapply agar kita bisa menguji ada tidaknya outlier pada setiap atribut yang ada pada df.
#Statistic Grubbs Test
sapply(df, function(df) grubbs.test(df))
## Score GDP.per.capita
## statistic numeric,2 numeric,2
## alternative "lowest value 2.853 is an outlier" "lowest value 0 is an outlier"
## p.value 1 1
## method "Grubbs test for one outlier" "Grubbs test for one outlier"
## data.name "df" "df"
## Social.support Healthy.life.expectancy
## statistic numeric,2 numeric,2
## alternative "lowest value 0 is an outlier" "lowest value 0 is an outlier"
## p.value 0.00262529 0.1873518
## method "Grubbs test for one outlier" "Grubbs test for one outlier"
## data.name "df" "df"
## Freedom.to.make.life.choices Generosity
## statistic numeric,2 numeric,2
## alternative "lowest value 0 is an outlier" "highest value 0.566 is an outlier"
## p.value 0.4379682 0.003153117
## method "Grubbs test for one outlier" "Grubbs test for one outlier"
## data.name "df" "df"
## Perceptions.of.corruption
## statistic numeric,2
## alternative "highest value 0.453 is an outlier"
## p.value 0.01703929
## method "Grubbs test for one outlier"
## data.name "df"
Syarat mendeteksi outlier pada metode ini yaitu dengan membandingkan nilai P-value dengan \(\alpha\), digunakan \(\alpha=0.05\), dengan keputusan Tolak \(H_0\) jika P-Value<\(\alpha\)
Keterangan:
\(H_0\): tidak terdapat outlier
\(H_1\): terdapat outlier
Sehingga didapatkan bahwa atribut yang terindikasi terdapat outlier yaitu Social.support; Generosity dan Perceptions.of.corruption.
#Histogram
col_num = colnames(df)
par(mar = c(3,3,1,1),
mfrow = c(2,2))
for (i in col_num) {
hist(df[[i]],
main = i,
las = 2,
col = "green")
}
Terakhir kita akan mencoba deteksi outlier dengan distance-based approach. Di sini kita menggunakan clustering. Clustering yang akan kita gunakan adalah clustering kmeans.
Pertama-tama kita akan menggunakan gap statistic method untuk menentukan jumlah cluster optimum.
Dari gap statistic method ditemukan bahwa cluster optimum adalah 5 cluster. Untuk itu kita akan melakukan clustering kmeans dengan 5 cluster pada variabel df dengan fungsi kmeans, lalu hasil dari clustering akan disimpan sebagai variabel km.res. Kemudian hasil dari clustering akan divisualisasikan menggunakan fungsi fviz_cluster.
#Clustering K-means
#Gap Statistic Method
fviz_nbclust(df, kmeans, method = "gap_stat")+
labs(subtitle = "Gap statistic method")
#K-means
km.res <- kmeans(df, 5)
fviz_cluster(km.res, df, ellipse.type = "norm")
Setelah melakukan gap statistic method, didapatkan bahwa jumlah cluster optimum sebanyak 5, maka selanjutnya dilakukan clustering dengan 5 cluster.
Pada visualisasi 5 cluster diatas didapatkan bahwa terdapat outlier pada data. Hal ini dapat dilihat dari terdapatnya nilai atau titik yang berada diluar centroid.
Dalam mengatasi outlier, kita menggunakan fungsi dari boxplot untuk remove outlier. Fungsi ini menggunakan prinsip IQR.
Setelah kita mencoba untuk remove outlier, ternyata penghapusan outlier menggunakan fungsi dari boxplot tidak cukup sekai remove untuk beberapa variabel. Untuk beberapa variabel diperlukan beberapa kali remove outlier. Misalnya pada atribut Social.support, kita perlu 4 kali remove outlier agar atribut Social.support bisa bersih dari outlier. Untuk itu, kita melakukan iterasi fungsi untuk remove outlier.
Remove outlier bisa diperlukan lebih dari sekali agar data benar benar bersih dari outlier dikarenakan pada saat outlier pada fase 1 diremove, ketika membuat boxplot di fase 2, whiskers dari boxplot di fase 2 pastinya akan berbeda dengan whiskers pada fase 1, maka memungkinkan untuk terbentuk outlier baru, begitu juga seterusnya.
Kita menggunakan fungsi dim untuk mengetahui dimension tepatnya kita ingin mengetahui banyaknya rows sebelum dan setelah dibersihkan outliernya
#Pembersihan Outlier
dim(df)
## [1] 156 7
#Atribut Social.support
boxplot.stats(df$Social.support)
## $stats
## [1] 0.5170 1.0555 1.2715 1.4530 1.6240
##
## $n
## [1] 156
##
## $conf
## [1] 1.221216 1.321784
##
## $out
## [1] 0.437 0.447 0.378 0.000
#Menghapus outlier pada atribut Social.support
for (i in (1:4)){
df <- df[-which(df$Social.support %in% boxplot.stats(df$Social.support)$out),]
}
#Atribut Healthy.life.expectancy
boxplot.stats(df$Healthy.life.expectancy)
## $stats
## [1] 0.1680 0.5775 0.8035 0.8920 1.1410
##
## $n
## [1] 148
##
## $conf
## [1] 0.7626542 0.8443458
##
## $out
## [1] 0
#Menghapus outlier pada atribut Healthy.life.expectancy
df <- df[-which(df$Healthy.life.expectancy %in% boxplot.stats(df$Healthy.life.expectancy)$out),]
#Atribut Freedom.to.make.life.choices
boxplot.stats(df$Freedom.to.make.life.choices)
## $stats
## [1] 0.0660 0.3175 0.4300 0.5080 0.6310
##
## $n
## [1] 147
##
## $conf
## [1] 0.4051748 0.4548252
##
## $out
## [1] 0.026
#Menghapus outlier pada atribut Freedom.to.make.life.choices
df <- df[-which(df$Freedom.to.make.life.choices %in% boxplot.stats(df$Freedom.to.make.life.choices)$out),]
#Atribut Generosity
boxplot.stats(df$Generosity)
## $stats
## [1] 0.0000 0.1070 0.1775 0.2520 0.3750
##
## $n
## [1] 146
##
## $conf
## [1] 0.1585395 0.1964605
##
## $out
## [1] 0.498 0.566
#Menghapus outlier pada atribut Generosity
df <- df[-which(df$Generosity %in% boxplot.stats(df$Generosity)$out),]
#Atribut Perceptions.of.corruption
boxplot.stats(df$Perceptions.of.corruption)
## $stats
## [1] 0.0000 0.0470 0.0835 0.1425 0.2780
##
## $n
## [1] 144
##
## $conf
## [1] 0.07092583 0.09607417
##
## $out
## [1] 0.393 0.410 0.341 0.298 0.343 0.373 0.380 0.308 0.290 0.316 0.310 0.453
## [13] 0.287 0.411
#Menghapus outlier pada atribut Perceptions.of.corruption
for (i in (1:3)){
df <- df[-which(df$Perceptions.of.corruption %in% boxplot.stats(df$Perceptions.of.corruption)$out),]
}
#Pembersihan Outlier
dim(df)
## [1] 124 7
Dapat dilihat bahwa banyak data yang dimiliki diawal sebanyak 156 data dengan 7 atribut. Setelah dilakukan pembersihan oulier, didapati bahwa data yang dimiliki tersisa sebanyak 124 data dengan 7 atribut.
Setelah melakukan pembersihan outlier, selanjutnya kita kembali mencoba deteksi outlier menggunakan 3 approach yang kita telah gunakan sebelumnya yaitu graphical approach (boxplot), statistical approach (grubb’s test) serta distance-based approach (k-means clustering). Coding yang digunakan pada bagian ini adalah sama persis dengan coding sebelum pembersihan outlier.
#Histogram
col_num = colnames(df)
par(mar = c(3,3,1,1),
mfrow = c(2,2))
for (i in col_num) {
hist(df[[i]],
main = i,
las = 2,
col = "green")
}
#Graphical Boxplot Test
par(mfrow=c(2,2))
for(i in 1:7) {boxplot(df[,i], main=names(df)[i])}
#Statistic Grubbs Test
sapply(df, function(df) grubbs.test(df))
## Score
## statistic numeric,2
## alternative "highest value 7.494 is an outlier"
## p.value 0.856768
## method "Grubbs test for one outlier"
## data.name "df"
## GDP.per.capita
## statistic numeric,2
## alternative "lowest value 0.073 is an outlier"
## p.value 1
## method "Grubbs test for one outlier"
## data.name "df"
## Social.support
## statistic numeric,2
## alternative "lowest value 0.666 is an outlier"
## p.value 0.7477548
## method "Grubbs test for one outlier"
## data.name "df"
## Healthy.life.expectancy
## statistic numeric,2
## alternative "lowest value 0.168 is an outlier"
## p.value 0.4964903
## method "Grubbs test for one outlier"
## data.name "df"
## Freedom.to.make.life.choices
## statistic numeric,2
## alternative "lowest value 0.066 is an outlier"
## p.value 0.6943657
## method "Grubbs test for one outlier"
## data.name "df"
## Generosity
## statistic numeric,2
## alternative "highest value 0.375 is an outlier"
## p.value 0.582165
## method "Grubbs test for one outlier"
## data.name "df"
## Perceptions.of.corruption
## statistic numeric,2
## alternative "highest value 0.183 is an outlier"
## p.value 1
## method "Grubbs test for one outlier"
## data.name "df"
#K-means
km.res <- kmeans(df, 5)
fviz_cluster(km.res, df, ellipse.type = "norm")