Introduction to Data Science

TUGAS 1

Email             :
RPubs            : https://rpubs.com/Calvinriswandy/
Jurusan          : Statistika
Address         : ARA Center, Matana University Tower
                         Jl. CBD Barat Kav, RT.1, Curug Sangereng, Kelapa Dua, Tangerang, Banten 15810.


Latar Belakang Data

jadi pada chapter ini kita akan lebih fokus untuk menjawab persoalan mengenai pertanyaan prediksi dan kita akan fokus kepada pengklasifikasian.

Import Data

library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.1.2
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5     v purrr   0.3.4
## v tibble  3.1.4     v dplyr   1.0.7
## v tidyr   1.2.0     v stringr 1.4.0
## v readr   2.0.1     v forcats 0.5.1
## Warning: package 'tidyr' was built under R version 4.1.2
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
pacman ::p_load(readxl, writexl)
Cancer <- read.csv("C:/Users/5/Documents/Semester2/Input/wdbc.csv")

Cancer

Data yang diperoleh merupakan Tumor Payudara yang dapat didiagnosis dengan melakukan biospi. Jadi, berdasarkan gambar digital yang dikumpulkan dari sampel berikut, ada 10 variabel berbeda yang diukur melalui inti sel dan ditentukan rata2 untuk setiap variabel di seluruh inti dicatat.

Penjelasan mengenai data penyakit Cancer

berikut adalah cara untuk mempermudah dalam memeriksa data saat data tersebut memiliki kolom yaitu dengan menggunakan fungsi glimpse.

glimpse(Cancer)
## Rows: 569
## Columns: 12
## $ ID                <int> 842302, 842517, 84300903, 84348301, 84358402, 843786~
## $ Class             <chr> "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M~
## $ Radius            <dbl> 1.0960995, 1.8282120, 1.5784992, -0.7682333, 1.74875~
## $ Texture           <dbl> -2.0715123, -0.3533215, 0.4557859, 0.2535091, -1.150~
## $ Perimeter         <dbl> 1.26881726, 1.68447255, 1.56512598, -0.59216612, 1.7~
## $ Area              <dbl> 0.98350952, 1.90703027, 1.55751319, -0.76379174, 1.8~
## $ Smoothness        <dbl> 1.56708746, -0.82623545, 0.94138212, 3.28066684, 0.2~
## $ Compactness       <dbl> 3.28062806, -0.48664348, 1.05199990, 3.39991742, 0.5~
## $ Concavity         <dbl> 2.65054179, -0.02382489, 1.36227979, 1.91421287, 1.3~
## $ Concave_Points    <dbl> 2.53024886, 0.54766227, 2.03543978, 1.45043113, 1.42~
## $ Symmetry          <dbl> 2.215565542, 0.001391139, 0.938858720, 2.864862154, ~
## $ Fractal_Dimension <dbl> 2.25376381, -0.86788881, -0.39765801, 4.90660199, -0~

Lalu karena kita akan bekerja menggunakan kelas sebagai variabel kategorikal, maka kita menggubahnya menjadi faktor menggunakan fungsi as_factor.

Cancer <- Cancer |>
  mutate(Class = as_factor(Class))
glimpse(Cancer)
## Rows: 569
## Columns: 12
## $ ID                <int> 842302, 842517, 84300903, 84348301, 84358402, 843786~
## $ Class             <fct> M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M~
## $ Radius            <dbl> 1.0960995, 1.8282120, 1.5784992, -0.7682333, 1.74875~
## $ Texture           <dbl> -2.0715123, -0.3533215, 0.4557859, 0.2535091, -1.150~
## $ Perimeter         <dbl> 1.26881726, 1.68447255, 1.56512598, -0.59216612, 1.7~
## $ Area              <dbl> 0.98350952, 1.90703027, 1.55751319, -0.76379174, 1.8~
## $ Smoothness        <dbl> 1.56708746, -0.82623545, 0.94138212, 3.28066684, 0.2~
## $ Compactness       <dbl> 3.28062806, -0.48664348, 1.05199990, 3.39991742, 0.5~
## $ Concavity         <dbl> 2.65054179, -0.02382489, 1.36227979, 1.91421287, 1.3~
## $ Concave_Points    <dbl> 2.53024886, 0.54766227, 2.03543978, 1.45043113, 1.42~
## $ Symmetry          <dbl> 2.215565542, 0.001391139, 0.938858720, 2.864862154, ~
## $ Fractal_Dimension <dbl> 2.25376381, -0.86788881, -0.39765801, 4.90660199, -0~

Pada Faktor ada yang disebut Tingkatansehingga bisa di anggap sebagai kategori. Kita dapat mengverivikasi level dengan menggunakan fungsi levels.

Cancer |>
  pull(Class) |>
  levels()
## [1] "M" "B"

Disini kita bisa melihat 2 macam kategori level, yaitu M yang berarti ganas dan B yang berarti jinak. Jadi kita menggunakan fungsi pull untuk mengekstrak satu kolom dan dilanjutkan ke fungsi level untuk melihat kategori kelas.

Mengeksplor data

Di bawah ini kami menggunakan fungsi group_by, meringkas dan n untuk menemukan jumlah dan persentase pengamatan tumor jinak dan ganas dalam kumpulan data. Fungsi n dalam ringkasan, ketika dipasangkan dengan group_by, menghitung jumlah pengamatan di setiap grup Kelas. Bisa diketahui bahwa kita menemukan 357 (63%) tumor jinak dan 212 (37%) pengamatan tumor ganas.

num_obs <- nrow(Cancer)
Cancer |>
  group_by(Class) |>
  summarize(
    count = n(),
    percentage = n() / num_obs * 100
)

Berikut ada visualisasi menggunakan Scatter plot.

perim_concav <- Cancer |>
  ggplot(aes(x = Perimeter, y = Concavity, color = Class)) +
  geom_point(alpha = 0.6) +
  labs(x = "Perimeter (standardized)", 
       y = "Concavity (standardized)",
       color = "Diagnosis") +
  scale_color_manual(labels = c("Malignant", "Benign"), 
                     values = c("Green", "Blue")) +
  theme(text = element_text(size = 12))
perim_concav

Klasifikasi dengan k-Nearest Neighbors

Untuk memprediksi observasi baru pada sebuah penelitian, kita perlu algoritma untuk melakukan klasifikasi. Laku kali ini kita akan menggunakan algoritma k-Nearest Neighbors. K adalah angka yang harus kita pilih.

Jarak Antar Titik

Untuk mencari k-Nearest Neighbors pada suatu observasi, kita harus menentukan jarak observasi baru dengan yang lama. Nanti nilai Knya akan dipilih berdasarkan jarak terdekat dengan objek observasi.

new_obs_Perimeter <- 0
new_obs_Concavity <- 3.5
Cancer |>
  select(ID, Perimeter, Concavity, Class) |>
  mutate(dist_from_new = sqrt((Perimeter - new_obs_Perimeter)^2 + 
                              (Concavity - new_obs_Concavity)^2)) |>
  arrange(dist_from_new) |>
  slice(1:10)

yang di eksplor lebih dari 2 variabel

kadang kita memerlukan 2 atau lebih data untuk mencari informasi dari data. Contohnya pada data ini kita akan menggunakan variabel perimeter, concavity, symetry.

new_obs_Perimeter <- 0
new_obs_Concavity <- 3.5
new_obs_Symmetry <- 1

Cancer |>
  select(ID, Perimeter, Concavity, Symmetry, Class) |>
  mutate(dist_from_new = sqrt((Perimeter - new_obs_Perimeter)^2 + 
                              (Concavity - new_obs_Concavity)^2 +
                                (Symmetry - new_obs_Symmetry)^2)) |>
  arrange(dist_from_new) |>
  slice(1:10)

k-Nearest Neighbors menggunakan tidymodels

pada k-Nearest Neighbors terkadang kita kesulitan ada mendapat masalah saat ingin mengendaikan kelas lebih dari 2 variabel. Dengan menggunakan tidymodels dapat membantu kita untuk membuat dan menggunakan model untuk mengklasifikasi data. Fungsi ini membuat kode lebih akurat dan simpel.

library(tidymodels)
## Warning: package 'tidymodels' was built under R version 4.1.2
## Registered S3 method overwritten by 'tune':
##   method                   from   
##   required_pkgs.model_spec parsnip
## -- Attaching packages -------------------------------------- tidymodels 0.1.4 --
## v broom        0.7.9      v rsample      0.1.1 
## v dials        0.1.0      v tune         0.1.6 
## v infer        1.0.0      v workflows    0.2.4 
## v modeldata    0.1.1      v workflowsets 0.1.0 
## v parsnip      0.1.7      v yardstick    0.0.9 
## v recipes      0.1.17
## Warning: package 'dials' was built under R version 4.1.2
## Warning: package 'infer' was built under R version 4.1.2
## Warning: package 'modeldata' was built under R version 4.1.2
## Warning: package 'parsnip' was built under R version 4.1.2
## Warning: package 'recipes' was built under R version 4.1.2
## Warning: package 'rsample' was built under R version 4.1.2
## Warning: package 'tune' was built under R version 4.1.2
## Warning: package 'workflows' was built under R version 4.1.2
## Warning: package 'workflowsets' was built under R version 4.1.2
## Warning: package 'yardstick' was built under R version 4.1.2
## -- Conflicts ----------------------------------------- tidymodels_conflicts() --
## x scales::discard() masks purrr::discard()
## x dplyr::filter()   masks stats::filter()
## x recipes::fixed()  masks stringr::fixed()
## x dplyr::lag()      masks stats::lag()
## x yardstick::spec() masks readr::spec()
## x recipes::step()   masks stats::step()
## * Learn how to get started at https://www.tidymodels.org/start/
cancer_train <- Cancer |>
  select(Class, Perimeter, Concavity)
cancer_train

lalu kita akan membuat spesifikasi algoritmanya dengan menggunakan fungsi nearest_neighbor dengan K=5 neighbor.

knn_spec <- nearest_neighbor(weight_func = "rectangular", neighbors = 5) |>
  set_engine("kknn") |>
  set_mode("classification")
knn_spec
## K-Nearest Neighbor Model Specification (classification)
## 
## Main Arguments:
##   neighbors = 5
##   weight_func = rectangular
## 
## Computational engine: kknn

agar sesuai dengan data yang kita miliki, kita perlu membuat spesifikasi modelnya dan data menggunakan fit. Lalu, kita juga perlu menentukan variabel yang digunakan sebagai prediktor menggunakan fungsi Class sebagai target dan perimeter dan concavity sebagai prediktor.

knn_fit <- knn_spec |>
  fit(Class ~ Perimeter + Concavity, data = cancer_train)

lalu kita bisa menggunakan cara berikut untuk mencari target variabel kecuali Class. Dan kita dapat memilih prediktor dengan simbol + dan jika ingin memilih semua menjadi prediktor menggunakan ..

knn_fit <- knn_spec |>
  fit(Class ~ ., data = cancer_train)
knn_fit
## parsnip model object
## 
## Fit time:  20ms 
## 
## Call:
## kknn::train.kknn(formula = Class ~ ., data = data, ks = min_rows(5,     data, 5), kernel = ~"rectangular")
## 
## Type of response variable: nominal
## Minimal misclassification: 0.07557118
## Best kernel: rectangular
## Best k: 5

Selanjutnya barulah kita bisa menggunakan fungsi predict

new_obs <- tibble(Perimeter = 0, Concavity = 3.5)
predict(knn_fit, new_obs)

saat menjalankan K-nearest neighbors secara manual, hasilnya akan menjadi malignant atau M. Kita akan berpikir bahwa malignant adalah hasil dari pengamatan ini.Namun, jawaban kita tidak bisa langsung mengambil kesimpulan karena, prediksi belum tentu benar. tetapi, kita bisa menghitung tingkat keakuratan dari prediksi kita.

Pemusatan dan Skala

Ketika menggunakan k-Nearest Neighbors skala variabel itu penting. Karena dalam mengklasifikasi kelas suatu objekyang kita prediksi, jarak observasi sangat berdampak. Saat melakukan pemusatan dan skala data yang harus kita lakukan adalah mecari rata-rata variabel pada data dan standar deviasi sehingga data kita dapat dikatakan memenuhi standar dan variabel.

unscaled_cancer <- read_csv("C:/Users/5/Documents/Semester2/Input/unscaled_wdbc.csv") |>
  mutate(Class = as_factor(Class)) |>
  select(Class, Area, Smoothness)
## Rows: 569 Columns: 12
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr  (1): Class
## dbl (11): ID, Radius, Texture, Perimeter, Area, Smoothness, Compactness, Con...
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
unscaled_cancer

terdapat perbedaan antara nilai area lebih besar dari nilai smoothness. Untuk mengetahui pengaruhnya terhadap hasil prediksi, maka kita harus membuat scatter plot dari dua prediktor.

uc_recipe <- recipe(Class ~ ., data = unscaled_cancer)
print(uc_recipe)
## Recipe
## 
## Inputs:
## 
##       role #variables
##    outcome          1
##  predictor          2
uc_recipe <- uc_recipe |>
  step_scale(all_predictors()) |>
  step_center(all_predictors()) |>
  prep()
uc_recipe
## Recipe
## 
## Inputs:
## 
##       role #variables
##    outcome          1
##  predictor          2
## 
## Training data contained 569 data points and no missing data.
## 
## Operations:
## 
## Scaling for Area, Smoothness [trained]
## Centering for Area, Smoothness [trained]
rare_cancer <- bind_rows(
      filter(Cancer, Class == "B"),
      Cancer |> filter(Class == "M") |> slice_head(n = 3)
    ) |>
    select(Class, Perimeter, Concavity)

rare_plot <- rare_cancer |>
  ggplot(aes(x = Perimeter, y = Concavity, color = Class)) +
  geom_point(alpha = 0.5) +
  labs(x = "Perimeter (standardized)", 
       y = "Concavity (standardized)",
       color = "Diagnosis") +
  scale_color_manual(labels = c("Malignant", "Benign"), 
                     values = c("orange2", "steelblue2")) +
  theme(text = element_text(size = 12))

rare_plot

jika kita menggunakan nilai K = 7 dan hanya dengan 3 pengamatan Tumor ganas. hasil klasifikasi akan selalu jinak tidak peduli dengan nilai cekung dan perimeter. Mengapa demikian? karena hasil sampel yang menunjukan tumor jinak ada 4 sampel, sehingga di ambil yang terbanyak.

library(themis)
## Warning: package 'themis' was built under R version 4.1.2
## Registered S3 methods overwritten by 'themis':
##   method                  from   
##   bake.step_downsample    recipes
##   bake.step_upsample      recipes
##   prep.step_downsample    recipes
##   prep.step_upsample      recipes
##   tidy.step_downsample    recipes
##   tidy.step_upsample      recipes
##   tunable.step_downsample recipes
##   tunable.step_upsample   recipes
## 
## Attaching package: 'themis'
## The following objects are masked from 'package:recipes':
## 
##     step_downsample, step_upsample
ups_recipe <- recipe(Class ~ ., data = rare_cancer) |>
  step_upsample(Class, over_ratio = 1, skip = FALSE) |>
  prep()
ups_recipe
## Recipe
## 
## Inputs:
## 
##       role #variables
##    outcome          1
##  predictor          2
## 
## Training data contained 360 data points and no missing data.
## 
## Operations:
## 
## Up-sampling based on Class [trained]
upsampled_cancer <- bake(ups_recipe, rare_cancer)

upsampled_cancer |>
  group_by(Class) |>
  summarize(n = n())

Menggunakan workflow

Dalam paket tidymodels ada yang namanya workflow yang berfungsi untuk merantai bersama sebuah langkah analisis data tanpa banyak kode yang diperlukan untuk proses klasifikasi datanya.

unscaled_cancer <- read_csv("C:/Users/5/Documents/Semester2/Input/unscaled_wdbc.csv") |>
  mutate(Class = as_factor(Class))
## Rows: 569 Columns: 12
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr  (1): Class
## dbl (11): ID, Radius, Texture, Perimeter, Area, Smoothness, Compactness, Con...
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# membuat KNN model
knn_spec <- nearest_neighbor(weight_func = "rectangular", neighbors = 7) |>
  set_engine("kknn") |>
  set_mode("classification")
uc_recipe <- recipe(Class ~ Area + Smoothness, data = unscaled_cancer) |>
  step_scale(all_predictors()) |>
  step_center(all_predictors())
knn_fit <- workflow() |>
  add_recipe(uc_recipe) |>
  add_model(knn_spec) |>
  fit(data = unscaled_cancer)
knn_fit
## == Workflow [trained] ==========================================================
## Preprocessor: Recipe
## Model: nearest_neighbor()
## 
## -- Preprocessor ----------------------------------------------------------------
## 2 Recipe Steps
## 
## * step_scale()
## * step_center()
## 
## -- Model -----------------------------------------------------------------------
## 
## Call:
## kknn::train.kknn(formula = ..y ~ ., data = data, ks = min_rows(7,     data, 5), kernel = ~"rectangular")
## 
## Type of response variable: nominal
## Minimal misclassification: 0.112478
## Best kernel: rectangular
## Best k: 7
new_observation <- tibble(Area = c(500, 1500), Smoothness = c(0.075, 0.1))
prediction <- predict(knn_fit, new_observation)

prediction

Sekarang kita akan melakukan analisis dengan langkah yang tidak memerlukan kode yang banyak.

# create the grid of area/smoothness vals, and arrange in a data frame
are_grid <- seq(min(unscaled_cancer$Area), 
                max(unscaled_cancer$Area), 
                length.out = 100)
smo_grid <- seq(min(unscaled_cancer$Smoothness), 
                max(unscaled_cancer$Smoothness), 
                length.out = 100)
asgrid <- as_tibble(expand.grid(Area = are_grid, 
                                Smoothness = smo_grid))

# use the fit workflow to make predictions at the grid points
knnPredGrid <- predict(knn_fit, asgrid)

# bind the predictions as a new column with the grid points
prediction_table <- bind_cols(knnPredGrid, asgrid) |> 
  rename(Class = .pred_class)

# plot:
# 1. the colored scatter of the original data
# 2. the faded colored scatter for the grid points
wkflw_plot <-
  ggplot() +
  geom_point(data = unscaled_cancer, 
             mapping = aes(x = Area, 
                           y = Smoothness, 
                           color = Class), 
             alpha = 0.75) +
  geom_point(data = prediction_table, 
             mapping = aes(x = Area, 
                           y = Smoothness, 
                           color = Class), 
             alpha = 0.02, 
             size = 5) +
  labs(color = "Diagnosis", 
       x = "Area (standardized)", 
       y = "Smoothness (standardized)") +
  scale_color_manual(labels = c("Malignant", "Benign"), 
                     values = c("orange2", "steelblue2")) +
  theme(text = element_text(size = 12))

wkflw_plot