Bahan webinar “Statistics using R” - Yevonnael Andrew
Untuk pertanyaan dan koreksi mohon hubungi saya melalui LinkedIn: https://www.linkedin.com/in/yevonnael-andrew-3351b9a7/
Jalankan kode di bawah untuk melakukan instalasi library. Jika Anda sudah pernah melakukan instalasi library di bawah ini, maka kode ini bisa dilompati.
Note: hilangkan tanda # untuk menjalankan kode (instalasi library)
# install.packages("tidyverse")
# install.packages("skimr")
# install.packages("GGally")
# install.packages("corrplot")
# install.packages("moderndive")
# install.packages("MASS")
# install.packages("lmtest")
Introduction
Setelah melakukan instalasi, kita perlu untuk memuat library yang diperlukan.
library(tidyverse)
library(skimr)
library(GGally)
library(corrplot)
library(moderndive)
library(MASS)
library(lmtest)
File yang akan digunakan adalah data.csv
# Memuat data
data <- read.csv("data.csv")
Lakukan inspeksi terhadap data.
head(data)
## Order.Date Ship.Date Ship.Mode Customer.ID Segment Product.ID
## 1 2016-11-08 2016-11-11 Second Class CG-12520 Consumer FUR-BO-10001798
## 2 2016-11-08 2016-11-11 Second Class CG-12520 Consumer FUR-CH-10000454
## 3 2016-06-12 2016-06-16 Second Class DV-13045 Corporate OFF-LA-10000240
## 4 2015-10-11 2015-10-18 Standard Class SO-20335 Consumer FUR-TA-10000577
## 5 2015-10-11 2015-10-18 Standard Class SO-20335 Consumer OFF-ST-10000760
## 6 2014-06-09 2014-06-14 Standard Class BH-11710 Consumer FUR-FU-10001487
## Category Sub.Category
## 1 Furniture Bookcases
## 2 Furniture Chairs
## 3 Office Supplies Labels
## 4 Furniture Tables
## 5 Office Supplies Storage
## 6 Furniture Furnishings
## Product.Name Sales
## 1 Bush Somerset Collection Bookcase 261.9600
## 2 Hon Deluxe Fabric Upholstered Stacking Chairs, Rounded Back 731.9400
## 3 Self-Adhesive Address Labels for Typewriters by Universal 14.6200
## 4 Bretford CR4500 Series Slim Rectangular Table 957.5775
## 5 Eldon Fold 'N Roll Cart System 22.3680
## 6 Eldon Expressions Wood and Plastic Desk Accessories, Cherry Wood 48.8600
## Quantity Discount Profit Ship.Duration Month Day IsWeekend
## 1 2 0.00 41.9136 3 November Tuesday Weekday
## 2 3 0.00 219.5820 3 November Tuesday Weekday
## 3 2 0.00 6.8714 4 June Sunday Weekend
## 4 5 0.45 -383.0310 7 October Sunday Weekend
## 5 2 0.20 2.5164 7 October Sunday Weekend
## 6 7 0.00 14.1694 5 June Monday Weekday
Melihat daftar kolom yang tersedia dan jenisnya.
summary(data)
## Order.Date Ship.Date Ship.Mode Customer.ID
## Length:9994 Length:9994 Length:9994 Length:9994
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## Segment Product.ID Category Sub.Category
## Length:9994 Length:9994 Length:9994 Length:9994
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## Product.Name Sales Quantity Discount
## Length:9994 Min. : 0.444 Min. : 1.00 Min. :0.0000
## Class :character 1st Qu.: 17.280 1st Qu.: 2.00 1st Qu.:0.0000
## Mode :character Median : 54.490 Median : 3.00 Median :0.2000
## Mean : 229.858 Mean : 3.79 Mean :0.1562
## 3rd Qu.: 209.940 3rd Qu.: 5.00 3rd Qu.:0.2000
## Max. :22638.480 Max. :14.00 Max. :0.8000
## Profit Ship.Duration Month Day
## Min. :-6599.978 Min. :0.000 Length:9994 Length:9994
## 1st Qu.: 1.729 1st Qu.:3.000 Class :character Class :character
## Median : 8.666 Median :4.000 Mode :character Mode :character
## Mean : 28.657 Mean :3.958
## 3rd Qu.: 29.364 3rd Qu.:5.000
## Max. : 8399.976 Max. :7.000
## IsWeekend
## Length:9994
## Class :character
## Mode :character
##
##
##
Format data belum tepat, maka kita perlu melakukan konversi jenis suatu variabel. * Konversi Order.Date dan Ship.Date menjadi jenis yang sesuai dengan as.Date * Konversi Customer.ID dan Product.Name menjadi jenis yang sesuai dengan as.Character
data[,1:2] <- lapply(data[,1:2], as.Date)
data[,c("Customer.ID", "Product.Name")] <- lapply(data[, c("Customer.ID", "Product.Name")],
as.character)
Mengecek ulang data.
summary(data)
## Order.Date Ship.Date Ship.Mode
## Min. :2014-01-03 Min. :2014-01-07 Length:9994
## 1st Qu.:2015-05-23 1st Qu.:2015-05-27 Class :character
## Median :2016-06-26 Median :2016-06-29 Mode :character
## Mean :2016-04-30 Mean :2016-05-03
## 3rd Qu.:2017-05-14 3rd Qu.:2017-05-18
## Max. :2017-12-30 Max. :2018-01-05
## Customer.ID Segment Product.ID Category
## Length:9994 Length:9994 Length:9994 Length:9994
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## Sub.Category Product.Name Sales Quantity
## Length:9994 Length:9994 Min. : 0.444 Min. : 1.00
## Class :character Class :character 1st Qu.: 17.280 1st Qu.: 2.00
## Mode :character Mode :character Median : 54.490 Median : 3.00
## Mean : 229.858 Mean : 3.79
## 3rd Qu.: 209.940 3rd Qu.: 5.00
## Max. :22638.480 Max. :14.00
## Discount Profit Ship.Duration Month
## Min. :0.0000 Min. :-6599.978 Min. :0.000 Length:9994
## 1st Qu.:0.0000 1st Qu.: 1.729 1st Qu.:3.000 Class :character
## Median :0.2000 Median : 8.666 Median :4.000 Mode :character
## Mean :0.1562 Mean : 28.657 Mean :3.958
## 3rd Qu.:0.2000 3rd Qu.: 29.364 3rd Qu.:5.000
## Max. :0.8000 Max. : 8399.976 Max. :7.000
## Day IsWeekend
## Length:9994 Length:9994
## Class :character Class :character
## Mode :character Mode :character
##
##
##
Statistik Deskriptif
Dalam sesi kali ini, kita akan membahas bagaimana mencari dan membandingkan ukuran sentral (mean, median, modus), variansi, dan bentuk distribusi data kita (apakah terdistribusi normal atau tidak)
1. Mencari rata-rata
sum(data$Profit)/length(data$Profit)
## [1] 28.6569
mean(data$Profit)
## [1] 28.6569
2. Mencari median
length(data$Profit)
## [1] 9994
Karena jumlah data kita genap, maka median adalah data ke 0.5*((N/2) + (N/2 + 1))
Untuk mencari median, data harus diurutkan dulu dari terkecil menjadi terbesar!
N = 9994
letakMedian_kiri = N/2
letakMedian_kanan = N/2+1
0.5*(sort(data$Profit)[letakMedian_kiri] + sort(data$Profit)[letakMedian_kanan])
## [1] 8.6665
median(data$Profit)
## [1] 8.6665
3. Mean vs Median
Dari profit yang kita hitung di atas, kita dapatkan dua jenis ukuran sentral, yaitu:
- Mean = 28.6569
- Median = 8.6665
Manakah ukuran yang lebih representatif?
Untuk membantu menjawab ini, mari kita pertimbangkan skenario lain yang lebih mudah dipahami.
Sekarang misalkan kita kumpulkan gaji 10 orang di sebuah perusahaan unicorn: (dalam juta rupiah)
gaji <- c(5, 6, 7, 5, 6, 7, 5, 6, 7, 7)
mean(gaji)
## [1] 6.1
median(gaji)
## [1] 6
Dari skenario di atas, besaran mean dan median dari sampel tersebut kurang lebih sama, sehingga apa yang kita pilih tidak terlalu masalah.
Sekarang misalkan data kita modifikasi sedikit, yaitu dengan mengikutsertakan gaji seorang CEO. Cukup satu orang saja!
gaji <- c(5, 6, 7, 5, 6, 7, 5, 6, 7, 7, 100) # misalkan gaji CEO 100 juta
mean(gaji)
## [1] 14.63636
median(gaji)
## [1] 6
Perhatikan bagaimana sekarang nilai mean melonjak tinggi, sedangkan nilai median TETAP SAMA.
Apa yang terjadi? Apakah kita adil dengan mengatakan bahwa gaji rata-rata di perusahaan unicorn ini 14.6 juta? Tentu tidak! Faktanya jika tidak menyertakan gaji CEO, gaji rata-rata hanyalah 6.1 juta-an!
Contoh di atas merupakan sebuah contoh bagaimana ukuran mean sangat sensitif terhadap outlier.
Sedangkan ukuran median tidak sensitif terhadap outlier. Untuk kasus di atas (seperti pengukuran gaji), maka nilai median lebih representatif. (Tentunya nanti bergantung kebutuhan kita apa)
Pesan moral: Berhati-hati ketika membaca berita yang melaporkan rata-rata, karena sangat berpotensi menimbulkan bias!
Mari kita tinjau kembali nilai mean dan median dari data kita.
mean(data$Profit)
## [1] 28.6569
median(data$Profit)
## [1] 8.6665
Di dalam statistika, ada modifikasi dari mean yang lebih tidak sensitif terhadap outlier, salah satu contohnya adalah Trimmed Mean. Dalam Trimmed Mean, kita akan membuang nilai ekstrim terbesar dan nilai ekstrim terkecil, atau dalam bahasa lain, kita hanya mengambil 95% yang berada di tengah-tengah data.
mean(data$Profit, trim = 0.05)
## [1] 19.16937
Angka yang dihasilkan Trimmed Mean tidak se-ekstrim mean biasa.
4. Modus (Mode)
Ukuran ini digunakan untuk variabel yang bersifat diskrit atau non-numerikal. Karena di R tidak ada fungsi bawaan untuk menghitung mode, maka kita perlu mendefinisikan fungsi kita sendiri.
getMode <- function(x) {
keys <- unique(x)
keys[which.max(tabulate(match(x, keys)))]
}
getMode(data$Month)
## [1] "November"
5. Menghitung simpanan baku dan variance
Simpangan baku dan variance menghitung sejauh mana nilai dalam distribusi berbeda satu sama lain. Dalam bahasa yang lebih sederhana: “seberapa menyimpang data ini dari nilai mean-nya”?
Jika data kita adalah populasi
variance = sum((data$Profit - mean(data$Profit))^2) / (length(data$Profit))
sd = sqrt(variance)
variance
## [1] 54872.31
sd
## [1] 234.2484
Jika data kita adalah sampel
variance = sum((data$Profit - mean(data$Profit))^2) / (length(data$Profit)-1)
sd = sqrt(variance)
variance
## [1] 54877.8
sd
## [1] 234.2601
Menggunakan fungsi bawaan R
Secara default, R akan menghitung variance dan simpanan baku sebagai sampel.
var(data$Profit)
## [1] 54877.8
sd(data$Profit) # sqrt(var(data$Profit))
## [1] 234.2601
Pada data kita atas, apakah data ini populasi atau sampel ternyata tidak terlalu relevan. Hal ini disebabkan karena jumlah observasi di data kita adalah N = 9994. Menurut teori statistika, semakin banyak N, maka akan semakin mendekati populasi.
Sekarang misalkan kita menghitung menggunakan data gaji perusahaan unicorn:
# Jika data adalah populasi
gaji <- c(5, 6, 7, 8, 9, 10, 5, 6, 8)
variance = sum((gaji - mean(gaji))^2) / (length(gaji))
sd = sqrt(variance)
variance
## [1] 2.765432
sd
## [1] 1.662959
# Jika data adalah sampel
gaji <- c(5, 6, 7, 8, 9, 10, 5, 6, 8)
variance = sum((gaji - mean(gaji))^2) / (length(gaji) - 1)
sd = sqrt(variance)
variance
## [1] 3.111111
sd
## [1] 1.763834
Simpanan baku pada data sampel akan lebih besar dibandingkan dengan data populasi. Hal ini karena ada ketidakpastian dan galat yang terkandung dalam sampling.
Ketika tidak ada variabilitas dalam data, maka nilai variance dan simpanan baku adalah nol.
jumlahJam <- c(24, 24, 24, 24, 24, 24, 24)
var(jumlahJam)
## [1] 0
sd(jumlahJam)
## [1] 0
6. Menghitung range, IQR, quantile
Kita juga bisa menggunakan macam-macam ukuran statistik lainnya, misalnya: range, IQR, dan quantile. Ukuran-ukuran ini umumnya digunakan untuk menyusun boxplot.
min(data$Profit)
## [1] -6599.978
max(data$Profit)
## [1] 8399.976
range(data$Profit) # mengembalikkan min dan max sekaligus
## [1] -6599.978 8399.976
IQR (Interquantile Range) adalah selisih data Q3 dan Q1. Median adalah Q2.
- Q1: 25% data
- Q2: 50% data
- Q3: 75% data
median(data$Profit)
## [1] 8.6665
as.numeric(quantile(data$Profit, 0.50))
## [1] 8.6665
IQR(data$Profit)
## [1] 27.63525
as.numeric(quantile(data$Profit, 0.75) - quantile(data$Profit, 0.25))
## [1] 27.63525
Meskipun kita dapat menggunakan quantile() untuk mendapatkan Q3 dan Q1 satu per satu, kedua angka ini juga disajikan bersama dengan kuratil ke-0 (min()), Q2 (median()), dan ke-100 (max()).
Satu set angka ini dinamakan five-number summary, yang dapat dipanggil menggunakan fungsi fivenum() atau summary()
fivenum(data$Profit)
## [1] -6599.9780 1.7280 8.6665 29.3640 8399.9760
# Five-number summary + mean
summary(data$Profit)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -6599.978 1.729 8.666 28.657 29.364 8399.976
Kita coba menggunakan variabel lain:
# Five-number summary + mean
summary(data$Ship.Duration)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 3.000 4.000 3.958 5.000 7.000
Five-number summary ini juga dapat disajikan dalam bentuk boxplot.
boxplot(data$Ship.Duration)
Exercise 1: Saham manakah yang tingkat volatilitasnya paling tinggi?
saham.A <- c(9999, 10200, 10500, 9800, 9900, 10500, 10900, 11000, 11500, 10500)
saham.B <- c(10000, 9500, 9900, 11000, 12000, 9800, 11500, 10500, 11000, 11500)
saham.C <- c(10000, 10100, 10200, 10000, 9900, 10000, 9900, 10500, 10300, 10200)
plot(saham.B, type = "l", col = "green")
lines(saham.A, col = "red")
lines(saham.C, col = "blue")
7. Menghitung covariance dan correlation
Misalkan kita memilih dua sampel, X dan Y, yang berukuran sama, lalu kita bisa menghitung covariance-nya, yaitu bagaimana variasi dalam sampel X memiliki keterkaitan dengan variasi dalam sampel Y.
Metrik ini banyak digunakan dalam dunia keuangan, misalnya dalam memilih saham untuk sebuah portofolio.
sum((saham.A - mean(saham.A))*(saham.B - mean(saham.B)))/(length(saham.B)-1)
## [1] 26074.44
cov(saham.A, saham.B)
## [1] 26074.44
Untuk menghitung korelasi.
- Nilai korelasi memiliki rentang -1 <= Cor(X,Y) <= 1
- Cor(X,Y) = 0 artinya tidak ada korelasi sama sekali antara X dan Y
- Cor(X,Y) = 1 atau -1 artinya ada korelasi sempurna antara X dan Y
cor(saham.A, saham.B)
## [1] 0.05685123
cor(saham.A, saham.C)
## [1] 0.6081219
Statistik Inferensial
https://id.wikipedia.org/wiki/Distribusi_normal https://id.wikipedia.org/wiki/Uji_hipotesis https://en.wikipedia.org/wiki/Standard_score
1. Menghitung nilai z
Nilai z adalah berapa standar deviasi skor tersebut dihitung dari mean. Distribusi data dianggap distribusi normal.
Contoh: Tinggi badan pria di Indonesia berdistribusi normal dengan rata-rata 160cm dan simpangan baku 7cm. Berapa peluang seorang pria yang dipilih secara acak lebih tinggi dari 175cm?
z <- (175-160)/7
pnorm(z, lower.tail = F)
## [1] 0.01606229
Jika rata-rata 160cm, maka berapa peluang seorang pria yang dipilih secara acak lebih tinggi dari 180cm?
z <- (180-160)/7
pnorm(z, lower.tail = F)
## [1] 0.002137367
Latihan: Misalkan kita memiliki rata-rata populasi 180cm dan simpangan baku 8cm, berapa probabilitas bahwa orang yang dipilih secara acak lebih pendek dari 174cm?
2. Menghitung interval kepercayaan
Pernah mendengar tingkat kepercayaan alfa = 0.05?
# Confidence interval 95%
qnorm(0.025)
## [1] -1.959964
# Confidence interval 99%
qnorm(0.005)
## [1] -2.575829
3. Uji Hipotesis dan p-value
Contoh: * a. Dari data sensus (populasi), misalkan pendapatan rata-rata per satu keluarga adalah 10 juta dengan simpanan baku 3 juta. * b. Sekarang kita melakukan sampling terhadap 30 keluarga, kita dapatkan rata-rata pendapatan per satu keluarga adalah 11 juta (sampel)
Pertanyaannya adalah: Apakah fluktuasi nilai pendapatan rata-rata yang ada di sampel kita ini hanya merupakan kebetulan (by chance karena randomness) atau memang keluarga ini berbeda dari keluarga pada umumnya?
Sekarang, kita asumsikan kita menggunakan tingkat kepercayaan 95%. Kita susun dulu hipotesis pengujian ini: * H0: mean sampel = mean sensus * H1: mean sampel TIDAK SAMA DENGAN mean sensus (two-sided test) * H1: mean sampel LEBIH KECIL atau LEBIH BESAR dari mean sensus (one-sided test)
z_stat <- (11 - 10) / (3 / sqrt(30))
z_stat
## [1] 1.825742
# P-value untuk uji two-sided
(1-pnorm(z_stat))*2
## [1] 0.06788915
Nilai z adalah 1.825. Nilai p-value 0.0679. Hasil TIDAK signifikan pada p < .05.
# P-value untuk uji one-sided
(1-pnorm(z_stat))
## [1] 0.03394458
Nilai z adalah 2.11. Nilai p-value 0.0339. Hasil signifikan pada p < .05.
4. Uji T-Test
Umumnya, uji-z digunakan ketika kita memiliki ukuran sampel yang cukup besar (aturan praktisnya adalah n >= 30) dan ketika simpangan baku populasi diketahui. Jika kondisi di atas tidak terpenuhi, kita dapat menggunakan pengukuran statistik yang dikenal sebagai uji-t Student.
Contoh: Diketahui 10 gaji karyawan dari perusahaan unicorn. Kita tahu dari data resmi bahwa rata-rata gaji adalah 10 juta, tapi kita tidak ketahui simpangan bakunya.
gaji <- c(9,8,8,9,10,11,12,8,7,9)
mean(gaji)
## [1] 9.1
- H0: mean gaji sampel SAMA dengan rata-rata data resmi
- H1: mean gaji sampel LEBIH KECIL dari rata-rata data resmi (one-sided test)
t.test(gaji, mu=10, alternative="less")
##
## One Sample t-test
##
## data: gaji
## t = -1.8676, df = 9, p-value = 0.04733
## alternative hypothesis: true mean is less than 10
## 95 percent confidence interval:
## -Inf 9.983367
## sample estimates:
## mean of x
## 9.1
- H0: mean gaji sampel SAMA dengan rata-rata data resmi
- H1: mean gaji sampel TIDAK SAMA dari rata-rata data resmi (two-sided test)
t.test(gaji, mu=10, alternative = "two.sided")
##
## One Sample t-test
##
## data: gaji
## t = -1.8676, df = 9, p-value = 0.09466
## alternative hypothesis: true mean is not equal to 10
## 95 percent confidence interval:
## 8.009879 10.190121
## sample estimates:
## mean of x
## 9.1
Jika nilai p kurang dari 0,05, kita menolak H0, maka kita bisa menyimpulkan bahwa memang ada perbedaan yang signifikan. Jika nilai p lebih besar dari 0,05, kita tidak dapat menyimpulkan bahwa ada perbedaan yang signifikan.
Extra Session
1. skim()
Secara pribadi, saya menyukai fungsi skim() dari paket skimr daripada glimpse() atau summary() karena memberikan informasi yang lebih rinci tentang data, termasuk missing data, jumlah data unik, jenis kolom dan untuk jenis numerik, skim() juga mengembalikan ringkasan lima angka dengan histogram kecil.
skim(data)
| Name | data |
| Number of rows | 9994 |
| Number of columns | 17 |
| _______________________ | |
| Column type frequency: | |
| character | 10 |
| Date | 2 |
| numeric | 5 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| Ship.Mode | 0 | 1 | 8 | 14 | 0 | 4 | 0 |
| Customer.ID | 0 | 1 | 8 | 8 | 0 | 793 | 0 |
| Segment | 0 | 1 | 8 | 11 | 0 | 3 | 0 |
| Product.ID | 0 | 1 | 15 | 15 | 0 | 1862 | 0 |
| Category | 0 | 1 | 9 | 15 | 0 | 3 | 0 |
| Sub.Category | 0 | 1 | 3 | 11 | 0 | 17 | 0 |
| Product.Name | 0 | 1 | 5 | 127 | 0 | 1850 | 0 |
| Month | 0 | 1 | 3 | 9 | 0 | 12 | 0 |
| Day | 0 | 1 | 6 | 9 | 0 | 7 | 0 |
| IsWeekend | 0 | 1 | 7 | 7 | 0 | 2 | 0 |
Variable type: Date
| skim_variable | n_missing | complete_rate | min | max | median | n_unique |
|---|---|---|---|---|---|---|
| Order.Date | 0 | 1 | 2014-01-03 | 2017-12-30 | 2016-06-26 | 1237 |
| Ship.Date | 0 | 1 | 2014-01-07 | 2018-01-05 | 2016-06-29 | 1334 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| Sales | 0 | 1 | 229.86 | 623.25 | 0.44 | 17.28 | 54.49 | 209.94 | 22638.48 | ▇▁▁▁▁ |
| Quantity | 0 | 1 | 3.79 | 2.23 | 1.00 | 2.00 | 3.00 | 5.00 | 14.00 | ▇▅▁▁▁ |
| Discount | 0 | 1 | 0.16 | 0.21 | 0.00 | 0.00 | 0.20 | 0.20 | 0.80 | ▇▆▁▁▁ |
| Profit | 0 | 1 | 28.66 | 234.26 | -6599.98 | 1.73 | 8.67 | 29.36 | 8399.98 | ▁▁▇▁▁ |
| Ship.Duration | 0 | 1 | 3.96 | 1.75 | 0.00 | 3.00 | 4.00 | 5.00 | 7.00 | ▂▃▇▅▃ |
2. ggpairs()
Dengan menggunakan ggpairs(), kita bisa membuat plot dari beberapa variabel sekaligus.
ggpairs(data[c('Sales','Profit','Quantity','Discount')])
3. Matriks Korelasi
Membuat matriks korelasi
cor_mat <- cor(data[c('Sales','Profit','Quantity','Discount')])
cor_mat
## Sales Profit Quantity Discount
## Sales 1.00000000 0.47906435 0.20079477 -0.02819012
## Profit 0.47906435 1.00000000 0.06625319 -0.21948746
## Quantity 0.20079477 0.06625319 1.00000000 0.00862297
## Discount -0.02819012 -0.21948746 0.00862297 1.00000000
Membuat plot dari matriks korelasi
corrplot(cor_mat, method="pie", type="lower", addCoef.col = "black")
4. Modelling
model_single <- lm(Profit ~ Sales, data=data)
get_regression_summaries(model_single)
## # A tibble: 1 x 9
## r_squared adj_r_squared mse rmse sigma statistic p_value df nobs
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.23 0.229 42279. 206. 206. 2976. 0 1 9994
5. Menguji Asumsi Normalitas
Salah satu asumsi dalam regresi linier adalah bahwa residual berdistribusi normal. Sekarang kita akan memplot Studentized Residuals model kita.
srs <- studres(model_single)
hist(srs, freq=FALSE,
main="Distribution of Studentized Residuals",
breaks=100)
xfit<-seq(min(srs),max(srs),length=40)
yfit<-dnorm(xfit)
lines(xfit, yfit)
Tampaknya data kita tidak berdistribusi normal dengan melihat grafik. Untuk memastikannya, kita harus menghitungnya secara statistik. Karena data kita melebihi 5000, kita harus menggunakan uji Kolmogorov-Smirnov.
ks.test(studres(model_single), data$Profit)
## Warning in ks.test(studres(model_single), data$Profit): p-value will be
## approximate in the presence of ties
##
## Two-sample Kolmogorov-Smirnov test
##
## data: studres(model_single) and data$Profit
## D = 0.76926, p-value < 2.2e-16
## alternative hypothesis: two-sided
- H0: Data mengikuti distribusi yang ditentukan
- HA: Data tidak mengikuti distribusi yang ditentukan
Karena p-value kita <0,5, maka H0 ditolak, sehingga data kita tidak terdistribusi normal.
6. Uji Heteroskedastisitas
Uji heteroskedastisitas bertujuan untuk menguji apakah dalam model regresi terjadi ketidaksamaan varian dari residual satu pengamatan ke pengamatan yang lain.
bptest(model_single)
##
## studentized Breusch-Pagan test
##
## data: model_single
## BP = 2723, df = 1, p-value < 2.2e-16
- H0 : Residual bersifat Homoskedastisitas
- HA : Residual bersifat Heteroskedastisitas
Karena p-value kita < 0,5, maka H0 ditolak, sehingga data error kita heteroskedastis, artinya data kita tidak terlalu cocok untuk menggunakan model regresi ini.
par(mfrow = c(2,2))
plot(model_single)
Ini adalah visualisasi dari residual model kita Dengan melihat Residuals vs Fitted, intinya terlihat seperti kipas, artinya semakin besar nilainya maka semakin besar pula residualnya. Kita harus mencoba untuk menormalkan mereka. Selain itu, dengan melihat Residuals vs Leverage, kita dapat melihat beberapa poin outlier yang akan kita lakukan analisis outlier.