Bab 4 Statistik Ringkasan
//TODO: Membahas tentang statistik ringkasan, cara mendapatkan dan menampilkannya menggunakan R.
Pada Bab ini kita akan menggunakan package {tidyverse}, {scales} dan {e1071}. Pastikan package tersebut sudah terinstall.
Data yang digunakan adalah data dari Flow_Of_Docs terminal JICT selama tahun 2020. Data ini sudah diolah dan disiapkan dalam file “fl_pelatihan.rds”. Oleh karena itu pastikan kita sudah import data tersebut dengan menjalankna perintah berikut ini.
Untuk mengetahui banyaknya data/baris/observasi dan kolom/variabel, kita dapat gunakan fungsi dim()
.
## [1] 71265 23
Ada sebanyak 71265 observasi dan 23 variabel pada data ini.
Untuk melihat beberapa baris data, gunakan fungsi head()
.
## # A tibble: 6 x 23
## tanggal container_id berth_time hari_berth waktu_berth iso_code
## <date> <chr> <dttm> <fct> <chr> <chr>
## 1 2019-12-21 APHU6242420 2019-12-20 09:30:20 Jumat 03:00-10:00 45G1
## 2 2019-12-21 APHU6242420 2019-12-20 09:30:20 Jumat 03:00-10:00 45G1
## 3 2019-12-20 APHU6247083 2019-12-20 09:30:20 Jumat 03:00-10:00 4500
## 4 2019-12-31 APHU6363910 2019-12-31 09:25:31 Selasa 03:00-10:00 4500
## 5 2019-12-31 APHU6364578 2019-12-31 09:25:31 Selasa 03:00-10:00 45G1
## 6 2019-12-31 APHU6364578 2019-12-31 09:25:31 Selasa 03:00-10:00 45G1
## # ... with 17 more variables: container_status <chr>, exim <chr>,
## # carrier <chr>, pol <chr>, pod <chr>, nama_negara_asal <chr>,
## # discharge_time <dttm>, stacking_time <dttm>, hari_stacking <fct>,
## # waktu_stacking <chr>, mita_non_mita <chr>, jalur <chr>, flag_lartas <chr>,
## # prenon_nonpre <chr>, postborder <chr>, karantina <chr>, dt <dbl>
## # A tibble: 10 x 23
## tanggal container_id berth_time hari_berth waktu_berth iso_code
## <date> <chr> <dttm> <fct> <chr> <chr>
## 1 2019-12-21 APHU6242420 2019-12-20 09:30:20 Jumat 03:00-10:00 45G1
## 2 2019-12-21 APHU6242420 2019-12-20 09:30:20 Jumat 03:00-10:00 45G1
## 3 2019-12-20 APHU6247083 2019-12-20 09:30:20 Jumat 03:00-10:00 4500
## 4 2019-12-31 APHU6363910 2019-12-31 09:25:31 Selasa 03:00-10:00 4500
## 5 2019-12-31 APHU6364578 2019-12-31 09:25:31 Selasa 03:00-10:00 45G1
## 6 2019-12-31 APHU6364578 2019-12-31 09:25:31 Selasa 03:00-10:00 45G1
## 7 2019-12-31 APHU6437822 2019-12-31 09:25:31 Selasa 03:00-10:00 45G1
## 8 2019-12-29 APHU6524402 2019-12-29 12:30:29 Minggu 10:00-18:00 4500
## 9 2019-12-25 APHU6584016 2019-12-25 14:15:25 Rabu 10:00-18:00 45G1
## 10 2019-12-20 APHU6601052 2019-12-20 09:30:20 Jumat 03:00-10:00 45G1
## # ... with 17 more variables: container_status <chr>, exim <chr>,
## # carrier <chr>, pol <chr>, pod <chr>, nama_negara_asal <chr>,
## # discharge_time <dttm>, stacking_time <dttm>, hari_stacking <fct>,
## # waktu_stacking <chr>, mita_non_mita <chr>, jalur <chr>, flag_lartas <chr>,
## # prenon_nonpre <chr>, postborder <chr>, karantina <chr>, dt <dbl>
4.1 Histogram
Kita lihat sebaran dari Dwelling Time (DT) terminal JICT selama tahun 2020.
fl_pelatihan %>%
ggplot(mapping = aes(x = dt)) +
geom_histogram(binwidth = 1, fill = "darkblue", color = "grey", alpha = 0.7) +
scale_y_continuous(labels = comma_format(big.mark = ".", decimal.mark = ",")) +
theme_minimal() +
labs(title = "Sebaran Dwelling Time Terminal JICT Tahun 2020",
caption = "*lebar selang = 1 hari",
x = "Dwelling Time (Hari)",
y = "Jumlah Kontainer") +
theme(text = element_text(size = 16),
plot.caption = element_text(face = "italic")
)
Kita ambil data dengan DT kurang dari atau sama dengan 25 hari kemudian kita lihat histogramnya.
fl_pelatihan %>%
filter(dt <= 25) %>%
ggplot(mapping = aes(x = dt)) +
geom_histogram(binwidth = 1, fill = "darkblue", color = "grey", alpha = 0.7) +
scale_y_continuous(labels = comma_format(big.mark = ".", decimal.mark = ",")) +
theme_minimal() +
labs(title = "Sebaran Dwelling Time Terminal JICT Tahun 2020",
subtitle = "Subset DT <= 25 Hari",
caption = "*lebar selang = 1 hari",
x = "Dwelling Time (Hari)",
y = "Jumlah Kontainer") +
theme(text = element_text(size = 16),
plot.caption = element_text(face = "italic")
)
Berikutnya kita subset lagi untuk data dengan DT kurang dari 5 hari dan lihat sebarannya.
fl_pelatihan %>%
filter(dt < 5) %>%
ggplot(mapping = aes(x = dt)) +
geom_histogram(binwidth = 0.1, fill = "darkblue", color = "grey", alpha = 0.7) +
scale_y_continuous(labels = comma_format(big.mark = ".", decimal.mark = ",")) +
theme_minimal() +
labs(title = "Sebaran Dwelling Time Terminal JICT Tahun 2020",
subtitle = "Subset DT < 5 Hari",
caption = "*lebar selang = 0.1 hari",
x = "Dwelling Time (Hari)",
y = "Jumlah Kontainer") +
theme(text = element_text(size = 16),
plot.caption = element_text(face = "italic")
)
Untuk membuat histogram dari kurva normal kita gunakan perintah berikut ini. Fungsi rnorm(100000)
adalah untuk membangkitkan bilangan acak dari sebaran Normal sebanyak 100.000 bilangan.
set.seed(1001)
xnorm <- rnorm(100000)
ggplot(data = data.frame(x = xnorm), mapping = aes(x)) +
geom_histogram(fill = "darkblue", color = "grey", alpha = 0.7) +
labs(x = NULL,
y = "frekuensi") +
theme_minimal()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
4.2 Data Numerik
Yang pertama kita akan membahas statistik ringkasan untuk data numerik.
4.2.1 Ukuran Pemusatan
4.2.1.1 Rataan
Rataan atau rata-rata (mean), dinotasikan dengan \(\bar{x}\), dapat diperoleh dengan cara berikut ini.
\[ \begin{align} \bar{x} & = \frac{x_1 + x_2 + x_3 + x_4 + \dots + x_n}{n} \\ & = \frac{1}{n}\sum_{i=1}^n x_i \end{align} \] dengan \(n\) adalah banyaknya data.
Misalkan sebuah vector x
berisi nilai x = {1, 3, 5, 2, 4, 6, 9}
. Maka rataan dari x
adalah
\[ \begin{align} \bar{x} & = \frac{1 + 3 + 5 + 2 + 4 + 6 + 9}{7} \\ & = \frac{30}{7} \\ & = 4.285714 \end{align} \]
Gunakan fungsi mean()
untuk memperoleh rataan.
## [1] 4.285714
## [1] 4.285714
Sekarang giliran Anda mencoba, berapakah nilai rataan dari Dwelling Time (DT) terminal JICT selama tahun 2020?
## [1] 3.574639
4.2.1.2 Median
Median (Me) adalah nilai yang berada pada posisi tengah-tengah setelah data diurutkan. Jika banyaknya data adalah ganjil maka posisinya ada di tengah, sedangkan jika banyaknya data adalah genap maka hitung nilai rataan dari dua data yang berada di tengah.
Misal x
berisi data {1, 3, 5, 2, 4, 6, 9}
maka median dari x
adalah
x' = {1, 2, 3, 4, 5, 6, 9}
Me = 4
Di R Anda dapat gunakan fungsi median()
untuk mendapatkan nilai tersebut dengan mudah.
## [1] 4
Untuk x
adalah data dengan banyaknya data adalah genap {1, 3, 5, 2, 4, 6}
maka median dari x
adalah
x' = {1, 2, 3, 4, 5, 6}
Me = (3 + 4)/2 = 3.5
## [1] 3.5
Berapakah nilai median dari DT terminal JICT selama tahun 2020?
## [1] 2.39
Jadi 50% amatan/kontainer yang masuk ke terminal JICT selama tahun 2020 memiliki DT di bawah 2.39 hari dan 50% amatan/kontainer lainnya memiliki DT di atas 2.39 hari.
4.2.1.3 Modus
Modus adalah nilai yang paling banyak muncul di dalam gugus data. R tidak tersedia fungsi untuk mendapatkan modus, sehingga kita perlu membuat fungsi sendiri. Berikut ini fungsi yang dapat digunakan untuk mengetahui nilai modus dari gugus data.
modus <- function(x, return_multiple = FALSE, na.rm = FALSE) {
if(na.rm){
x <- na.omit(x)
}
ux <- unique(x)
freq <- tabulate(match(x, ux))
mode_loc <- if(return_multiple) which(freq == max(freq)) else which.max(freq)
return(ux[mode_loc])
}
## x
## 1 2 3 4 5 6 7 8 9 10
## 40 45 58 47 56 58 55 46 54 41
Dengan fungsi modus()
diperoleh nilai modus
## [1] 3
Untuk tetap mendapatkan semua nilai modus jika ada lebih dari satu modus maka gunakan argumen return_multiple = TRUE
.
## [1] 3 6
Berpakah modus dari DT terminal JICT selama tahun 2020?
## [1] 0.42
## [1] 0.42 0.35
4.2.2 Ukuran Penyebaran
4.2.2.1 Range
Range adalah selisih nilai terbesar dan terkecil pada suatu gugus data.
\[ \text{Range} = X_{\text{max}} - X_{\text{min}} \]
Pada program R, fungsi range()
menghasilkan dua nilai, yaitu \(X_{\text{min}}\) dan \(X_{\text{max}}\).
## [1] 1 10
Jika ingin mendapatkan nilai range yang berupa selisih antara dua nilai tersebut kita dapat gunakan fungsi diff()
## [1] 9
Berapa range dari DT terminal JICT selama tahun 2020?
## [1] 0.00 230.71
## [1] 230.71
4.2.2.2 Inter-Quartile Range
Inter-Quartile Range atau Jangkauan Antar Kuartil diperoleh dengan cara
\[ \text{IQR} = Q_3 - Q_1\]
Dengan program R kita gunakan fungsi quantile()
untuk mendapatkan nilai \(Q_1\) dan \(Q_3\). Karena \(Q_1\) adalah data ke 25% dan \(Q_3\) adalah data ke 75%, maka kita tuliskan pada argumen probs
.
## 25% 75%
## 3 8
## 75%
## 5
Untuk mendapatkan nilai-nilai tersebut dapat menggunakan fungsi summary()
.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 3.000 6.000 5.538 8.000 10.000
Mari kita lihat summary dari DT terminal JICT selama tahun 2020.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 1.160 2.390 3.575 4.470 230.710
4.2.2.3 Ragam dan Simpangan Baku
Ragam dari data contoh dapat dihitung dengan
\[s^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2\]
Dengan program R dapat diperoleh dengan fungsi var()
.
## [1] 7.535627
Karena simpangan baku contoh adalah akar kuadrat dari ragam maka diperoleh dengan
\[s = \sqrt{s^2}\]
sedangkan dengan R dapat diperoleh menggunakan fungsi sqrt()
dari hasil var()
atau langsung dengan fungsi sd()
.
## [1] 2.74511
## [1] 2.74511
Berapakah ragam dan simpangan baku dari DT terminal JICT selama tahun 2020?
## [1] 15.6407
## [1] 3.954833
4.2.3 Ukuran Bentuk Sebaran
4.2.3.1 Skewness
Formula untuk mendapatkan nilai skewness adalah
\[\text{skewness} = \frac{\sum_{i=1}^{n}(x_i-\bar{x})^3}{n \times s^3}\]
Untuk memperoleh nilai skewness kita perlu fungsi dari package {e1071}, yaitu fungsi skewness()
.
## [1] 1.907461
Untuk skewness dengan koefisien Fisher-Pearson
\[\text{skewness} = \frac{\sqrt{n(n-1)}}{n-2} \times \frac{\sum_{i=1}^{n}(x_i-\bar{x})^3}{n \times s^3}\]
## [1] 1.913197
Karena skewness bernilai positif artinya bentuk sebaran data lebih menjulur ke kanan. Untuk melihatnya kita dapat memmbuat histogram dari data tersebut.
data.frame(x = x) %>%
ggplot(mapping = aes(x)) +
geom_histogram(bins = 6, fill = "grey", color = "white") +
theme_minimal()
Pada data yang menulur ke sebelah kiri
data.frame(x = -x) %>%
ggplot(mapping = aes(x)) +
geom_histogram(bins = 6, fill = "grey", color = "white") +
theme_minimal()
## [1] -1.907461
Berapa nilai skewness dari DT terminal JICT selama tahun 2020?
## [1] 5.273619
4.2.3.2 Kurtosis
Formula kurtosis yang digunakan secara default pada fungsi kurtosis()
dari package {e1071} adalah
\[\text{kurtosis} = \frac{\sum_{i=1}^{n}(x_i-\bar{x})^4}{n \times s^4} - 3\]
set.seed(1001)
x <- rnorm(100000)
data.frame(x = x) %>%
ggplot(mapping = aes(x = x)) +
geom_histogram(bins = 30, fill = "darkblue", color = "grey", alpha = 0.7) +
theme_minimal()
## [1] 0.002579773
Berapa nilai kurtosis dari DT terminal JICT selama tahun 2020 dan apa artinya?
## [1] 163.1807
Kurtosis bernilai positif dan nilainya pun cukup tinggi, artinya ekor sebaran data sangat kurus dibandingkan sebaran normal.
4.3 Data Kategorik
Statistik ringkasan pada data kategorik pertama dan paling sering digunakan adalah menghitung banyaknya kategori atau kelas pada sebuah gugus data. Misalnya pada data fl_pelatihan
ada variable kategorik, diantaranya yaitu jalur
. Untuk mendapatkan banyaknya amatan pada masing-masing jalur, kita dapat gunakan perintah berikut ini.
## # A tibble: 3 x 2
## jalur n
## <chr> <int>
## 1 HIJAU 67255
## 2 KUNING 546
## 3 MERAH 3464
Hasil seperti di atas juga sering disebut sebagai tabel frekuensi. Untuk mengetahui proporsi atau persentase dai masing-masing kategori terhadap total data gunakan perintah berikut ini.
## # A tibble: 3 x 3
## jalur n persentase
## <chr> <int> <dbl>
## 1 HIJAU 67255 0.944
## 2 KUNING 546 0.00766
## 3 MERAH 3464 0.0486
Kita dapat visualisasikan dalam bentuk diagram batang atau bar chart.
fl_pelatihan %>%
count(jalur) %>%
mutate(pct = round(n/sum(n)*100, 2)) %>%
ggplot(mapping = aes(x = reorder(jalur, -n), y = n, fill = jalur, color = jalur)) +
geom_bar(stat = "identity") +
geom_text(aes(label = paste0(pct, "%")), color = "black", vjust = -0.25, size = 8) +
scale_y_continuous(labels = scales::comma_format(big.mark = ".", decimal.mark = ","),
limits = c(0, 70000)) +
scale_fill_manual(values = c("MERAH" = "red",
"KUNING" = "yellow",
"HIJAU" = "green")) +
scale_color_manual(values = c("MERAH" = "red",
"KUNING" = "yellow",
"HIJAU" = "green")) +
labs(x = "Jalur",
y = "Jumlah Kontainer") +
theme_minimal() +
theme(legend.position = "none",
text = element_text(size = 16),
panel.grid.minor = element_blank())
Kita dapat menghitung rataan harga rumah yang terjual berdasarkan banyaknya kamar tidur.
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 3 x 2
## jalur avg_dt
## <chr> <dbl>
## 1 HIJAU 3.17
## 2 KUNING 6.93
## 3 MERAH 10.8
Tentunya seperti yang sudah diketahui bahwa rataan DT untuk kontainer yang melalui jalur Hijau lebih kecil (lebih cepat) dibandingkan dengan jalur yang lain. Kita bisa juga menampilkannya menggunakan barplot.
fl_pelatihan %>%
group_by(jalur) %>%
summarise(avg_dt = mean(dt)) %>%
ungroup() %>%
ggplot(mapping = aes(x = jalur, y = avg_dt, fill = jalur, color = jalur)) +
geom_col(alpha = 0.7) +
scale_fill_manual(values = c("MERAH" = "red",
"KUNING" = "yellow",
"HIJAU" = "green")) +
scale_color_manual(values = c("MERAH" = "red",
"KUNING" = "yellow",
"HIJAU" = "green")) +
labs(x = "Jalur",
y = "Rataan DT (Hari)") +
theme_minimal() +
theme(legend.position = "none",
text = element_text(size = 16),
panel.grid.minor = element_blank())
## `summarise()` ungrouping output (override with `.groups` argument)
Misalnya kita juga ingin mengetahui frekuensi banyaknya kontainer berdasarkan jalur dan lartas.
## `summarise()` regrouping output by 'jalur' (override with `.groups` argument)
## # A tibble: 6 x 3
## jalur flag_lartas n
## <chr> <chr> <int>
## 1 HIJAU N 42548
## 2 HIJAU Y 24707
## 3 KUNING N 456
## 4 KUNING Y 90
## 5 MERAH N 2718
## 6 MERAH Y 746
Tampilannya akan lebih mudah dibaca jika kita buat menjadi tabulasi silang.
fl_pelatihan %>%
group_by(jalur, flag_lartas) %>%
summarise(n = n()) %>%
pivot_wider(id_cols = jalur,
names_from = flag_lartas,
names_prefix = "lartas ",
values_from = n,
values_fill = 0)
## `summarise()` regrouping output by 'jalur' (override with `.groups` argument)
## # A tibble: 3 x 3
## # Groups: jalur [3]
## jalur `lartas N` `lartas Y`
## <chr> <int> <int>
## 1 HIJAU 42548 24707
## 2 KUNING 456 90
## 3 MERAH 2718 746
Atau kita lihat dalam nilai proporsinya.
fl_pelatihan %>%
group_by(jalur, flag_lartas) %>%
summarise(n = n()) %>%
mutate(persentase = n/sum(n))
## `summarise()` regrouping output by 'jalur' (override with `.groups` argument)
## # A tibble: 6 x 4
## # Groups: jalur [3]
## jalur flag_lartas n persentase
## <chr> <chr> <int> <dbl>
## 1 HIJAU N 42548 0.633
## 2 HIJAU Y 24707 0.367
## 3 KUNING N 456 0.835
## 4 KUNING Y 90 0.165
## 5 MERAH N 2718 0.785
## 6 MERAH Y 746 0.215
fl_pelatihan %>%
group_by(jalur, flag_lartas) %>%
summarise(n = n()) %>%
mutate(persentase = n/sum(n)) %>%
pivot_wider(id_cols = jalur,
names_from = flag_lartas,
names_prefix = "lartas ",
values_from = persentase,
values_fill = 0)
## `summarise()` regrouping output by 'jalur' (override with `.groups` argument)
## # A tibble: 3 x 3
## # Groups: jalur [3]
## jalur `lartas N` `lartas Y`
## <chr> <dbl> <dbl>
## 1 HIJAU 0.633 0.367
## 2 KUNING 0.835 0.165
## 3 MERAH 0.785 0.215
Agar hasilnya lebih enak dilihat, kita tampilkan hanya dua angka dibelakang desimal dengan fungsi round()
.
fl_pelatihan %>%
group_by(jalur, flag_lartas) %>%
summarise(n = n()) %>%
mutate(persentase = round(n/sum(n)*100, 2)) %>%
pivot_wider(id_cols = jalur,
names_from = flag_lartas,
names_prefix = "lartas ",
values_from = persentase,
values_fill = 0)
## `summarise()` regrouping output by 'jalur' (override with `.groups` argument)
## # A tibble: 3 x 3
## # Groups: jalur [3]
## jalur `lartas N` `lartas Y`
## <chr> <dbl> <dbl>
## 1 HIJAU 63.3 36.7
## 2 KUNING 83.5 16.5
## 3 MERAH 78.5 21.5
Visualisasi berupa stacked barplot.
fl_pelatihan %>%
group_by(jalur, flag_lartas) %>%
summarise(n = n()) %>%
mutate(persentase = round(n/sum(n), 4)) %>%
ggplot(mapping = aes(x = jalur, y = persentase, fill = flag_lartas)) +
geom_col(alpha = 0.7) +
scale_y_continuous(labels = scales::percent_format()) +
labs(x = "Jalur",
y = "Persentase Jumlah Kontainer",
fill = "Lartas") +
theme_minimal() +
theme(text = element_text(size = 16))
## `summarise()` regrouping output by 'jalur' (override with `.groups` argument)