1 R Studio UI

knitr::include_graphics("assets/RStudio_UI.PNG")

2 Basic R Programming

2.1 Introduction to R Markdown

Bagian putih dari R Markdown (.Rmd) berguna untuk menulis narasi. Pada bagian ini dapat ditambahkan heading dengan menambahkan hashtag # sebelum kalimat. Narasi yang tidak ditambahkan # sebelum kalimat akan menjadi paragraf biasa.

Bagian abu-abu dari Rmarkdown adalah chunk. Chunk berguna untuk menulis code.

# code di sini
1+1
#> [1] 2

2.2 Object

Untuk pengolahan data di R, data atau sebuah value dapat disimpan/diassign ke dalam objek. Untuk assign objek dapat menggunakan <- dan hasilnya akan tersimpan pada environment.

# melakukan assignment
nama <- "Algoritma"

# print isi objek
nama
#> [1] "Algoritma"
# kota <- "Jakarta"

2.3 R is Case Sensitive

"Algoritma" == "algoritma"
#> [1] FALSE
"Algoritma" == "Algoritma"
#> [1] TRUE
"Algoritma" != "algoritma"
#> [1] TRUE

2.4 Comment

Untuk memasukkan narasi dalam chunk dapat menggunakan comment dengan menambahkan # sebelum narasi tersebut. Bagian code yang diberi comment tidak akan dieksekusi.

# ini adalah comment
1+1 # operasi matematika
#> [1] 2

2.5 Overwrite

Nilai yang disimpan adalah nilai terakhir yang dieksekusi.

kota <- "Jakarta"
kota <- "Bandung"
kota <- "Denpasar"
kota <- "Palembang"

Kota <- "Jakarta"

# ini adalah nilai yang akan disimpan

Panduan untuk penamaan objek:

  • Boleh dikombinasikan antara huruf dan angka
  • Untuk kombinasi angka dan huruf, angka tidak boleh diletakkan di paling depan/awal
  • Tidak diizinkan adanya spasi, untuk penghubung bisa menggunakan tanda (_)
  • Tidak mengizinkan adanya karakter seperti !.$.%, dll
  • Berikan nama yang merepresentasikan data yang akan dibaca
  • Penamaan objek mengikuti aturan R yang case sensitive
# contoh penamaan objek sesuai ketentuan R
sales_2018 <- 2018

2.6 🧠 Dive Deeper

Buatlah 3 buah object sebagai berikut:

  • nama: nama lengkap Anda
  • pekerjaan: pekerjaan Anda saat ini
  • kota: domisili Anda

Gunakan komentar untuk memperjelas code yang diketikkan

# code here

nama <- "Fafilia"
pekerjaan <- "Instructor DS"
kota <- "Jakarta Selatan"

2.7 Data Types

Sebelum membahas tentang tipe data apa saja yang terdapat di R. Ada 2 fungsi yang akan kita bahas terlebih dahulu, dengan tujuan untuk mempermudah kita dalam berkenalan dengan tipe-tipe data di R.

Fungsi c() -> combine nilai untuk menyimpan lebih dari satu nilai

student <- c("Rangga", "Mulatua","Gimin","Purwanto","Peter","Fikri")

Funcsi class() -> melihat tipe data pada sebuat object

class(student)
#> [1] "character"

2.7.1 Character

Tipe data yang berisi huruf/karakter.

tempat <- c("Bandung", "Jakarta", "Bogor")

Contoh lain data yang memiliki tipe character:

  • UserId, NIM, NIK, CustomerId, NoInvoice
  • Nama, Email, Alamat, dll

2.7.2 Numeric

Tipe data berisi angka yang dapat berupa angka kontinu (ada koma/pecahan), maupun diskrit (bilangan bulat tanpa koma).

tinggi <- c(170.5, 165, 168.5)
class(tinggi)
#> [1] "numeric"

Contoh lain data yang memiliki tipe numeric:

  • Harga
  • Temperatur, berat badan, dll

2.7.3 Integer

Tipe data berisi angka yang berupa angka diskrit (bilangan bulat tanpa koma). Untuk memaksa numeric menjadi integer, dapat gunakan L dibelakang angka.

umur <- c(25L, 34L, 27L, 17L)
class(umur)
#> [1] "integer"

Contoh lain data yang memiliki tipe integer:

  • jumlah student
  • jumlah pengunjung
  • skala survey

2.7.4 Logical

Tipe data yang hanya berisi TRUE atau FALSE. Penulisan TRUE/FALSE dapat disingkat menjadi T/F.

status <- c(TRUE, FALSE, T, F)
class(status)
#> [1] "logical"

Contoh lain data yang memiliki tipe logical:

  • 0/1 -> Churn/not Churn

2.7.5 Implicit Coercion

Lalu, apa yang akan terjadi jika dalam satu data memiliki beberapa tipe data yang berbeda seperti chunk dibawah ini?

mix <- c("Algoritma", 2022, TRUE)
class(mix)
#> [1] "character"

Bila Anda perhatikan setiap nilai pada object mix memiliki petik dua, artinya nilai tersebut merupakan sebuah objek dengan tipe character. Proses perubahan paksa dari suatu vector bisa disebut sebagai implicit coercion. Ilustrasi terjadinya implicit coercion dapat dilihat pada gambar di bawah ini:

knitr::include_graphics("assets/data_type.png")

imajiner <- 4+7i

class(imajiner)
#> [1] "complex"

2.8 ❓ Knowledge Check

  1. Di bawah ini mana pernyataan yang salah terkait sifat pemrograman di R ?
  • Bahasa pemrograman R bersifat case sensitive
  • Tanda <- berfungsi untuk menyimpan suatu nilai ke dalam sebuah objek
  • Tanda // diawal sebuah chunk berfungsi sebagai tanda komentar
  • tanda == digunakan untuk mengecek kesamaan antar 2 buah nilai
  1. Tipe data yang tepat untuk kolom umur student adalah …
  • Logical
  • Integer
  • Character
  • Numeric
  1. Jawablah tipe data dari beberapa object di bawah ini:
object1 <- c(TRUE, 1L, 1/2)
object2 <- c(TRUE, "TRUE", 1, 1.0)
object3 <- c(1, 2, 3, 4L)
  • Tipe data object1 adalah numeric
  • Tipe data object2 adalah character
  • Tipe data object3 adalah numeric

2.9 Data Structure

Struktur data merupakan bagaimana data disusun berdasarkan struktur tertentu, pada R terdapat 4 struktur data dasar yaitu vector, matrix, list, dan dataframe.

2.9.1 Vector

Vector merupakan salah satu struktur data yang sering digunakan. Vector merupakan struktur data yang hanya bisa menampung 1 tipe data saja dan hanya terdiri dari satu dimensi. Fungsi c() digunakan untuk membuat sebuah vector.

kelas <- c("Sparta Day Online", "Sparta Night Online", "Sparta Night")
levels(kelas)
#> NULL

2.9.2 Factor

Factor merupakan bentuk perkembangan dari vector, yang membedakan vector dan factor adalah objek factor memiliki levels. Digunakan untuk tipe data kategorikal.

card <- factor(c("Blue", "Gold", "Platinum", "Gold", "Gold"))
class(card)
#> [1] "factor"
levels(card)
#> [1] "Blue"     "Gold"     "Platinum"

Contoh Factor yang lain:

  • Gender, Tingkat pendidikan
  • Golongan darah, departement/divisi, dll

2.9.3 Matrix

Matrix merupakan struktur data yang memiliki 2 dimensi dan hanya bisa diisi dengan 1 tipe data saja.

# tidak perlu fokus pada pembuatan object matrix
mat <- matrix(data = 11:16, nrow = 3, ncol = 2)
mat
#>      [,1] [,2]
#> [1,]   11   14
#> [2,]   12   15
#> [3,]   13   16
mat[3,1]
#> [1] 13

2.9.4 List

List merupakan struktur data yang dapat menyimpan lebih dari 1 tipe data dan hanya memiliki 1 dimensi

# tidak perlu fokus pada pembuatan object list
our_list <- list(c(TRUE, FALSE), "TRUE", c(1, 6, 12), 1L)
our_list
#> [[1]]
#> [1]  TRUE FALSE
#> 
#> [[2]]
#> [1] "TRUE"
#> 
#> [[3]]
#> [1]  1  6 12
#> 
#> [[4]]
#> [1] 1

Seperti vector, sebuah list hanya memiliki 1 dimensi; namun jika Anda ingin mengakses elemen-elemen data di dalamnya, Anda dapat menggunakan []. Meskipun kita sudah menggunakan [], kita masih akan mendapatkan objek dengan struktur data berupa list:

Jika ingin mengakses element pada list bisa menggunakan tanda []

our_list[1]
#> [[1]]
#> [1]  TRUE FALSE

Untuk mengakses vector yang ada di dalamnya, maka kita bisa menggunakan [[]]:

our_list[[1]][1]
#> [1] TRUE

2.9.5 Data Frame

Data frame merupakan tipe data yang paling sering digunakan dalam pengolahan data, karena data frame dapat berisi beberapa tipe data serta memiliki 2 dimensi. Adapun cara untuk membuat sebuah data frame kita bisa menggunakan fungsi data.frame() seperti di bawah ini:

# cara 1: dari vector

nama <- c("Rany","Fafil")
kota <- c("Palembang","Jakarta")

data.frame(nama=nama, kota=kota)
# cara 2: langsung

data.frame(nama = c("Rany","Fafil"),
           kota = c("Palembang","Jakarta"))

Berikut rangkuman dari ke-empat struktur data yang sudah kita bahas di atas:

knitr::include_graphics("assets/structure.png")

——-END OF DAY 1—————–

——-START OF DAY 2—————

2.10 🧠 Dive Deeper

Buat sebuah data frame yang berisi 3 baris dengan kolom sebagai berikut:

  • product_name: nama produk di pasar swalayan (bebas/yang sering Anda beli)
  • quantity: jumlah pembelian masing-masing produk
  • harga: harga satuan untuk masing-masing produk

Simpan pada object yang bernama product

# code here
product <- data.frame(product_name = c("susu","cabai","gula"),
           quantity = c(1,2,5),
           harga = c(3000,5000,10000))

3 Working with Data Frame

3.1 Directory

Fungsi getwd() untuk mengetahui working directory (tempat bekerja) dari file Rmd.

getwd()
#> [1] "C:/Users/fafiliam/Downloads/1_programming_for_data_science-main"

Fungsi setwd() untuk mengatur lokasi dari working directory.

# untuk menjalankan setwd() harap dirun di console
# setwd("...")

3.2 Read and extracting data

Kita akan menganalisis data retail.csv yang terdapat pada folder data_input. Gunakan fungsi read.csv() untuk membaca file CSV ke R, lalu simpanlah ke sebuah object dengan nama retail.

retail <- read.csv("data_input/retail.csv", row.names = "Row.ID")

Deskripsi kolom:

  • Row.ID = Nomer baris
  • Order.ID = Unique ID pemesanan
  • Order.Date = Tanggal pemesanan
  • Ship.Date = Tanggal pengiriman barang
  • Ship.Mode = Jenis pengiriman yang dipilih customer
  • Customer.ID = Unique ID customer
  • Segment = Segmentasi/kategori custoemr
  • Product.ID = Unique ID barang
  • Category = Kateogri barang
  • Sub.Category = Sub Kategori barang
  • Product.Name = Nama produk barang
  • Sales = Total sales dari barang yang dibeli oleh customer
  • Quantity = Total barang yang dibeli oleh customer
  • Discount = Total diskon yang diberikan kepada customer
  • Profit = Total keuntungan yang didapatkan oleh perusahaan

Notes : di read.csv jika ingin mempertahankan spasi untuk nama kolom bisa menggunakan check.names=FALSE

3.2.1 View()

Pada umumnya ketika bekerja dengan data kita ingin melihat data bentuk data secara keseluruhan, hal tersebut dapat dilakukan dengan menggunakan fungsi View().

# View(retail)

Notes: tidak dianjurkan karena apabila data berukuran besar maka berpotensi melambatkan komputer.

3.2.2 head() and tail()

Daripada melihat keseluruhan data, lebih baik kita “mengintip” sebagian baris yang dapat merepresentasikan bentuk keseluruhan data.

Fungsi head() untuk melihat beberapa baris teratas pada data (default 6)

head(x=retail)

Fungsi tail() untuk melihat beberapa data terakhir.

tail(n= 8, x=retail)

3.2.3 str()

Fungsi str() untuk melihat struktur dari dataframe.

str(retail)
#> 'data.frame':    9994 obs. of  14 variables:
#>  $ Order.ID    : chr  "CA-2016-152156" "CA-2016-152156" "CA-2016-138688" "US-2015-108966" ...
#>  $ Order.Date  : chr  "11/8/16" "11/8/16" "6/12/16" "10/11/15" ...
#>  $ Ship.Date   : chr  "11/11/16" "11/11/16" "6/16/16" "10/18/15" ...
#>  $ Ship.Mode   : chr  "Second Class" "Second Class" "Second Class" "Standard Class" ...
#>  $ Customer.ID : chr  "CG-12520" "CG-12520" "DV-13045" "SO-20335" ...
#>  $ Segment     : chr  "Consumer" "Consumer" "Corporate" "Consumer" ...
#>  $ Product.ID  : chr  "FUR-BO-10001798" "FUR-CH-10000454" "OFF-LA-10000240" "FUR-TA-10000577" ...
#>  $ Category    : chr  "Furniture" "Furniture" "Office Supplies" "Furniture" ...
#>  $ Sub.Category: chr  "Bookcases" "Chairs" "Labels" "Tables" ...
#>  $ Product.Name: chr  "Bush Somerset Collection Bookcase" "Hon Deluxe Fabric Upholstered Stacking Chairs, Rounded Back" "Self-Adhesive Address Labels for Typewriters by Universal" "Bretford CR4500 Series Slim Rectangular Table" ...
#>  $ Sales       : num  262 731.9 14.6 957.6 22.4 ...
#>  $ Quantity    : int  2 3 2 5 2 7 4 6 3 5 ...
#>  $ Discount    : num  0 0 0 0.45 0.2 0 0 0.2 0.2 0 ...
#>  $ Profit      : num  41.91 219.58 6.87 -383.03 2.52 ...

3.2.4 dim(), nrow(), ncol()

Fungsi dim() untuk mengetahui dimensi dari dataframe.

dim(retail)
#> [1] 9994   14

Fungsi nrow() untuk mengetahui jumlah baris, sedangkan ncol() untuk mengetahui jumlah kolom.

nrow(retail)
#> [1] 9994
ncol(retail)
#> [1] 14

3.2.5 summary()

Fungsi summary() untuk mengetahui ringkasan/rangkuman statistik dari dataframe.

summary(retail)
#>    Order.ID          Order.Date         Ship.Date          Ship.Mode        
#>  Length:9994        Length:9994        Length:9994        Length:9994       
#>  Class :character   Class :character   Class :character   Class :character  
#>  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
#>                                                                             
#>                                                                             
#>                                                                             
#>  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         
#>  Min.   :0.0000   Min.   :-6599.978  
#>  1st Qu.:0.0000   1st Qu.:    1.729  
#>  Median :0.2000   Median :    8.666  
#>  Mean   :0.1562   Mean   :   28.657  
#>  3rd Qu.:0.2000   3rd Qu.:   29.364  
#>  Max.   :0.8000   Max.   : 8399.976

Pada kolom numerik, ditampilkan ringkasan lima nilai (five number summary). Apakah ada insight yang menarik:

  • Rata-rata pembelian oleh customer pada data retai adalah sebanyak 3 unit (dilihat dari quantity)
  • Rata-rata penjualan/Sales untuk seluruh product adalah 229.858
  • Ada kerugian dimana pada kolom Profit ditemukan penjualan yang < 0

3.3 ❓ Knowledge Check

  1. Code yang tepat untuk melihat 10 baris terakhir pada data retail yaitu …
  • head(retail, 10)
  • str(retail)
  • summary(retail, 10)
  • tail(retail, 10)
  1. Fungsi yang digunakan untuk menampilkan dimensi data serta tipe data setiap kolom secara sekaligus yaitu …
  • dim()
  • ncol()
  • class()
  • str()

3.4 Performing simple data cleansing

3.4.1 Explicit Coercion

Tahapan awal sebelum melakukan analisis data adalah memastikan bahwa data yang digunakan sudah bersih. Salah satu teknik data cleansing yaitu mengubah tipe data ke dalam tipe data yang tepat, atau dikenal sebagai istilah explicit coercion.

# cek kembali struktur data retail
str(retail)
#> 'data.frame':    9994 obs. of  14 variables:
#>  $ Order.ID    : chr  "CA-2016-152156" "CA-2016-152156" "CA-2016-138688" "US-2015-108966" ...
#>  $ Order.Date  : chr  "11/8/16" "11/8/16" "6/12/16" "10/11/15" ...
#>  $ Ship.Date   : chr  "11/11/16" "11/11/16" "6/16/16" "10/18/15" ...
#>  $ Ship.Mode   : chr  "Second Class" "Second Class" "Second Class" "Standard Class" ...
#>  $ Customer.ID : chr  "CG-12520" "CG-12520" "DV-13045" "SO-20335" ...
#>  $ Segment     : chr  "Consumer" "Consumer" "Corporate" "Consumer" ...
#>  $ Product.ID  : chr  "FUR-BO-10001798" "FUR-CH-10000454" "OFF-LA-10000240" "FUR-TA-10000577" ...
#>  $ Category    : chr  "Furniture" "Furniture" "Office Supplies" "Furniture" ...
#>  $ Sub.Category: chr  "Bookcases" "Chairs" "Labels" "Tables" ...
#>  $ Product.Name: chr  "Bush Somerset Collection Bookcase" "Hon Deluxe Fabric Upholstered Stacking Chairs, Rounded Back" "Self-Adhesive Address Labels for Typewriters by Universal" "Bretford CR4500 Series Slim Rectangular Table" ...
#>  $ Sales       : num  262 731.9 14.6 957.6 22.4 ...
#>  $ Quantity    : int  2 3 2 5 2 7 4 6 3 5 ...
#>  $ Discount    : num  0 0 0 0.45 0.2 0 0 0.2 0.2 0 ...
#>  $ Profit      : num  41.91 219.58 6.87 -383.03 2.52 ...

Untuk mengubah tipe data, kita bisa menggunakan fungsi as.___() di mana ___ diisi dengan tipe data tujuan. Contoh:

  • as.character()
  • as.Date()
  • as.integer()
  • as.numeric()
  • as.factor()
  • dan sebagainya

Diskusi: Dari data retail, kolom manakah saja yang perlu diubah tipe datanya?

  • Ship.Mode , Category, Sub.Category, Segment -> kolom yang harus diubah ke factor
  • Order.Date, Ship.Date -> Date
# explicit coercion
retail$Ship.Mode <- as.factor(retail$Ship.Mode)
retail$Category <- as.factor(retail$Category)
retail$Sub.Category <- as.factor(retail$Sub.Category)
retail$Segment <- as.factor(retail$Segment)

# levels untuk cek unique values yang ada pada 1 kolom factor
# levels(retail$Ship.Mode)

Parameter format pada as.Date() digunakan untuk menspesifikan format penulisan tanggal pada data, berikut format yang sering digunakan:

  • YEAR
    • %Y = tahun empat digit, contoh: 2022
    • %y = tahun dua digit, contoh: 22
  • MONTH
    • %B = nama bulan, contoh: January
    • %b = nama bulan singkatan, contoh: Jan
    • %m = bulan dua digit, contoh: 01
  • DAY
    • %A = nama hari, contoh: Monday
    • %d = tanggal, contoh: 01 sampai 31
# explicit coercion data waktu
# Order.Date -> %m/%d/%y
# Ship.Date -> %m/%d/%y

retail$Order.Date <- as.Date(retail$Order.Date, format="%m/%d/%y") #format = format data asli sebelum perubahan dilakukan
retail$Ship.Date <- as.Date(retail$Ship.Date, format="%m/%d/%y")

Ketika tipe data kolom sudah tepat, maka summary lebih informatif:

  • Date: dapat melihat range tanggal
  • Factor: dapat melihat frekuensi untuk masing-masing levels
str(retail)
#> 'data.frame':    9994 obs. of  14 variables:
#>  $ Order.ID    : chr  "CA-2016-152156" "CA-2016-152156" "CA-2016-138688" "US-2015-108966" ...
#>  $ Order.Date  : Date, format: "2016-11-08" "2016-11-08" ...
#>  $ Ship.Date   : Date, format: "2016-11-11" "2016-11-11" ...
#>  $ Ship.Mode   : Factor w/ 4 levels "First Class",..: 3 3 3 4 4 4 4 4 4 4 ...
#>  $ Customer.ID : chr  "CG-12520" "CG-12520" "DV-13045" "SO-20335" ...
#>  $ Segment     : Factor w/ 3 levels "Consumer","Corporate",..: 1 1 2 1 1 1 1 1 1 1 ...
#>  $ Product.ID  : chr  "FUR-BO-10001798" "FUR-CH-10000454" "OFF-LA-10000240" "FUR-TA-10000577" ...
#>  $ Category    : Factor w/ 3 levels "Furniture","Office Supplies",..: 1 1 2 1 2 1 2 3 2 2 ...
#>  $ Sub.Category: Factor w/ 17 levels "Accessories",..: 5 6 11 17 15 10 3 14 4 2 ...
#>  $ Product.Name: chr  "Bush Somerset Collection Bookcase" "Hon Deluxe Fabric Upholstered Stacking Chairs, Rounded Back" "Self-Adhesive Address Labels for Typewriters by Universal" "Bretford CR4500 Series Slim Rectangular Table" ...
#>  $ Sales       : num  262 731.9 14.6 957.6 22.4 ...
#>  $ Quantity    : int  2 3 2 5 2 7 4 6 3 5 ...
#>  $ Discount    : num  0 0 0 0.45 0.2 0 0 0.2 0.2 0 ...
#>  $ Profit      : num  41.91 219.58 6.87 -383.03 2.52 ...

Tambahan: Kolom dengan tipe data date dapat dioperasikan satu sama lain. Misal kita ingin menghitung durasi waktu antara pemesanan (Order.Date) dengan pengiriman (Ship.Date), lalu simpan hasil perhitungan ke kolom Duration.

Fungsi difftime() digunakan untuk menghitung time1 - time2 dengan parameter:

  • time1: waktu end
  • time2: waktu start
  • units: satuan waktu hasil pengurangan, bisa diisi dengan secs, mins, hours, days, weeks
# hitung Duration
retail$Duration <-difftime(time1 = retail$Ship.Date,
         time2 = retail$Order.Date,
         units = "days")

3.4.2 Check Missing Value

Fungsi anyNA() digunakan untuk mengetahui apakah pada data terdapat missing value.

anyNA(retail)
#> [1] FALSE

Fungsi is.na() digunakan untuk mengecek missing value pada setiap nilai. Fungsi colSums() digunakan untuk menjumlahkan nilai pada setiap kolom.

colSums(is.na(retail))
#>     Order.ID   Order.Date    Ship.Date    Ship.Mode  Customer.ID      Segment 
#>            0            0            0            0            0            0 
#>   Product.ID     Category Sub.Category Product.Name        Sales     Quantity 
#>            0            0            0            0            0            0 
#>     Discount       Profit     Duration 
#>            0            0            0

Kesimpulan:

Proses imputasi missing value lebih dalamnya akan dibahas pada course Machine Learning.

# contoh NA
as.numeric(c(12, 23, "-"))
#> [1] 12 23 NA

Beberapa cara yang dapat dilakukan untuk mengisi NA:

  • Menghapus baris atau kolom
  • Mengisi NA dengan sebuah nilai (imputasi):
    • Dari sumber data lain, misal dari database, dll
    • Dari hasil perhitungan kolom lain
    • Isi dengan sebuah nilai yang merepresentasikan
    • Pendekatan statistik, contoh: mean, median, modus (ukuran pemusatan)

3.4.3 Cek duplikasi data

any(duplicated(retail))
#> [1] TRUE
retail[duplicated(retail),]

3.4.4 Subsetting

Subsetting adalah teknik untuk mengambil sebagian data yang diperlukan untuk proses analisis. Gunakan kurung siku [] setelah nama object Untuk melakukan subsetting. Berikut ilustrasinya:

knitr::include_graphics("assets/subset.png")

Hint: nama_object[index_baris, index_kolom]

Dari data retail, ambil index baris 10 hingga 20.

retail[10:20,]

Dari data retail, ambil kolom Ship.Mode dan Segment saja

retail[,c("Ship.Mode","Segment")]
# retail[,c(4,6)] # akan menghasilkan output yang sama dengan code di atas

Bagaimana untuk menggabungkan subset baris dan kolom dari dua kasus di atas?

retail[10:20,c("Ship.Mode","Segment")]

3.4.4.1 Conditional Subsetting

Kita dapat menggunakan operator logikal berikut untuk melakukan filter baris berdasarkan kondisi tertentu.

Logical Operator:

  • > lebih dari
  • < kurang dari
  • >= lebih dari sama dengan
  • <= kurang dari sama dengan
  • == mengecek kesamaan 2 nilai
  • != tidak sama dengan
  • & dan
  • | atau

Dari data retail, ambil baris yang memiliki Profit lebih dari 4000 lalu ambil kolom Product.Name beserta nilai Profitnya

retail[retail$Profit>4000,c("Product.Name","Profit")]

Berapa banyak transaksi yang dilakukan oleh Segment Corporate yang nilai Profitnya di atas 500?

cor500 <- retail[retail$Segment=="Corporate"&retail$Profit>500,] #jangan lupa untuk menambahkan koma setelah filter bagian baris
nrow(cor500)
#> [1] 35

Berapa banyak transaksi yang pengirimannya (Ship.Mode) menggunakan Second Class dan Standard Class?

nrow(retail[retail$Ship.Mode=="Second Class"|retail$Ship.Mode=="Standard Class",])
#> [1] 7913

Dengan operator %in%:

# not in
`%!in%` <- Negate("%in%") # untuk yang notin tidak ada jadi harus buid sendiri functionnya
retail[retail$Ship.Mode %!in% c("Second Class","Standard Class"),]
# in
retail[retail$Ship.Mode %in% c("Second Class","Standard Class"),]

—————–END OF DAY2——————- —————–START OF DAY3—————

3.5 🧠 Dive Deeper

Anda sebagai seorang analis diminta tolong oleh Fulan selaku kepala divisi Sales, untuk menelusuri performa penjualan perusahaan retail ini. Dibawah ini ada, 3 pertanyaan bisnis yang ditanyakan:

  1. Ada berapa banyak transaksi barang dengan Category Furniture yang tipe pengirimannya (Ship.Mode) adalah Standard Class?
nrow(retail[retail$Category=="Furniture"&retail$Ship.Mode=="Standard Class",])
#> [1] 1248
  1. Ada berapa banyak transaksi dari Category Furniture yang mengakibatkan kerugian (Profit kurang dari nol)?
nrow(retail[retail$Category=="Furniture"&retail$Profit<0,]) 
#> [1] 714
  1. Simpan hasil filter pada nomor sebelumnya ke sebuah object, kemudian gunakan fungsi summary() untuk mengetahui Sub.Category dari Furniture apa yang paling banyak menyebabkan kerugian?
furniture_loss <- retail[retail$Category=="Furniture"&retail$Profit<0,]
sort(summary(furniture_loss$Sub.Category), decreasing = T)[1]
#> Chairs 
#>    235
# untuk mengubah ke data frame agar orientasinya long format
as.data.frame(sort(summary(furniture_loss$Sub.Category), decreasing = T))
# untuk mengambil data pada summary di index ke 1 dan 3
summary(furniture_loss$Sub.Category)[c(1,3)]
#> Accessories         Art 
#>           0           0

3.6 Data Aggregation

Selain subsetting, hal yang sering dilakukan ketika kita melakukan analisis adalah aggregasi data, yaitu membuat tabel rangkuman.

3.6.1 table()

Fungsi table() untuk menampilkan frekuensi tiap kategori

Kita sebagai seorang analyst bisa memanfatkan fungsi table() untuk mencari tahu Segment manakah yang paling banyak melakukan transaksi pada data retail?

sort(table(retail$Segment), decreasing = T)
#> 
#>    Consumer   Corporate Home Office 
#>        5191        3020        1783

Contoh kasus lain, untuk mencari tahu tipe pengiriman (Ship.Mode) apa yang paling banyak digunakan oleh Segment consumer?

as.data.frame(table(retail$Ship.Mode, retail$Segment,retail$Sub.Category))
as.data.frame(table(retail$Ship.Mode, retail$Segment))

3.6.2 prop.table()

Mengubah tabel frekuensi menjadi tabel proporsi/persentase untuk tiap kategori.

Sintaks: prop.table(table(...))

Fungsi prop.table() dalam data retail dapat kita manfaatkan untuk mengetahui proporsi transaksi untuk masing-masing Segment pelanggan.

prop.table(table(retail$Segment))*100
#> 
#>    Consumer   Corporate Home Office 
#>    51.94116    30.21813    17.84070

3.6.3 Cross Tabulation

Fungsi xtabs() untuk menampilkan jumlah (sum) suatu variabel numerik untuk tiap kategori.

Sintaks: xtabs(formula = ..., data = ...)

Parameter:

  • formula dituliskan dengan numerik ~ kategorik (simbol ~ disebut tilde)
  • data dituliskan dengan nama object data yang digunakan

Dikarenakan fungsi xtabs() diperuntuhkan untuk menjumlahkan, kita bisa menggunakannya untuk menghitung jumlah Profit yang dihasilkan untuk setiap Category!

sort(xtabs(formula=Profit~Category, data=retail), decreasing = T)
#> Category
#>      Technology Office Supplies       Furniture 
#>       145454.95       122490.80        18451.27

Fungsi xtabs() tidak hanya bisa digunakan untuk satu value saja. Sebagai contoh, kita ingin menghitung jumlah Sales yang diperoleh dari masing-masing Category dan setiap Segment.

xtabs(Sales~Category+Segment, retail)
#>                  Segment
#> Category          Consumer Corporate Home Office
#>   Furniture       391049.3  229019.8    121930.7
#>   Office Supplies 363952.1  230676.5    124418.4
#>   Technology      406399.9  246450.1    183304.0

Insight: -Dari semua segmen pelanggan penjualan Sales terbanyak pada Technology

3.6.4 Aggregate

Untuk melakukan aggregasi data dengan fungsi yang lebih fleksibel, kita dapat menggunakan fungsi aggregate().

Fungsi aggregate() untuk menghitung nilai statistik tertentu (jumlah, rata-rata, dll) berdasarkan kolom kategori dalam data.

Sintaks: aggregate(x = ..., data = ..., FUN = ...)

Parameter:

  • x dituliskan dengan numerik ~ kategorik
  • data dituliskan dengan nama object data yang digunakan
  • FUN dituliskan dengan nama fungsi:
    • sum: jumlah
    • min: nilai minimum
    • max: nilai maksimum
    • mean: nilai rata-rata
    • median: nilai tengah
    • length: count (menghitung frekuensi)

Hitung nilai rata-rata Sales untuk setiap Segment

aggregate(x=Sales~Segment,data=retail,FUN=mean)

Hitung nilai rata-rata Sales untuk setiap Segment dan Category. Tampilkan baris dengan nilai rata-rata Sales yang tertinggi dan terendah saja.

agg_sales <- aggregate(Sales~Segment+Category, data=retail, FUN=mean)

agg_sales <- agg_sales[order(agg_sales$Sales, decreasing = T),] #order akan melakukan sorting dengan mengembalikan nilai index

# menggabungkan data terendah dan tertinggi
rbind(head(agg_sales,1),tail(agg_sales,1))

Gunakan fungsi order() untuk mengurutkan nilai, perlu diingat output dari order() adalah urutan index sehingga perlu dikombinasikan dengan subsetting [] untuk mengurutkan object dataframe.

3.6.5 Quick Summary Tables

  • table() untuk membuat tabel frekuensi dari data kategorik
  • prop.table() untuk membuat tabel proporsi dari data kategorik
  • xtabs() untuk membuat tabel yang menjumlahkan(sum) nilai numerik berdasarkan data kategorik
  • aggregate() untuk membuat tabel agregasi untuk menghitung nilai statistika dari data numerik berdasarkan data-data kategorik

3.6.6 🧠 Dive Deeper

  1. Kategori barang dengan jumlah kuantitas yang paling banyak terjual adalah …, sedangkan yang paling sedikit adalah …
# Pak Gimin
xtabs(Quantity~Category, retail)
#> Category
#>       Furniture Office Supplies      Technology 
#>            8028           22906            6939
  • Kuantitas penjualan terbanyak berasal dari kategori Office Supplies dan yang terendah adalah dari kategori Technology
  1. Cari tahu nilai tengah (median) durasi pengiriman untuk masing-masing tipe pengiriman, lalu jawab pertanyaan berikut:

Jika seorang pelanggan memilih tipe pengiriman Second Class, barang yang dikirim pada hari Rabu maka perkiraan akan sampai pada hari …

# Mas Vetrick

aggregate(x=Duration~Ship.Mode, data=retail, FUN=median)

Insight : Perkiraan barang sampai jika menggunakan jenis pengiriman Second Class adalah hari Sabtu

  1. Pasangan segmen pelanggan dan kategori barang yang mendatangkan jumlah keuntungan terbesar adalah …, sedangkan yang terkecil adalah …
# Pak Rangga

agg_profit <- aggregate(Profit~Segment+Category,retail,sum)

# [c(1,9),] -> dimaksudkan untuk mengambil baris ke 1 dan 9 serta mengambil seluruh kolom
agg_profit[order(agg_profit$Profit, decreasing=T),][c(1,9),]
# MAs Vetrick

as.data.frame(xtabs(Profit~Segment+Category, retail))
  1. Data retail adalah data transaksi dari tahun 2014 sampai 2017. Anda diminta untuk menghitung jumlah keuntungan yang diperoleh pada setiap kategori barang, namun hanya untuk order yang terjadi pada tahun 2017 saja (Hint: Order.Date di antara tanggal “2017-01-01” dan “2017-12-31”).
# Pak Purwanto

retail2017 <- retail[retail$Order.Date>=as.Date("2017-01-01")&retail$Order.Date<=as.Date("2017-12-31"),]

aggregate(Profit~Category, retail2017, FUN=sum)
retail[retail$Order.Date>="2017-01-01"&retail$Order.Date<="2017-12-31",]

3.7 Sampling Data

Fungsi sample() digunakan untuk mengambil beberapa baris secara acak pada data. Biasanya digunakan pada proses machine learning.

# contoh sampling sederhana menggunakan vector
student <- c("A", "B", "C", "D")
sample(student, 3)
#> [1] "B" "C" "A"

Fungsi set.seed() digunakan untuk mengunci random number generator sehingga hasil sampling tidak berubah setiap kali run code. Nilai seed yang digunakan bebas, maksimal 10 digit.

set.seed(1)
# untuk repetisi bisa menggunakan replace=TRUE tetapi kurang disarankan
sample(student, 3, replace = TRUE)
#> [1] "A" "D" "C"

Tambahan: Untuk sampling dari data.frame, harus dibuat objek berisi index baris yang akan diambil. Index baris dibuat secara random, kemudian diambil baris sesuai index yang sudah dibuat.

Berikut adalah contoh untuk melakukan sampel sebanyak 60% observasi dari data retail

set.seed(100)

# buat index baris secara random
index <- sample(nrow(retail), # jumlah baris data
                nrow(retail)*0.6) # jumlah baris yang ingin diambil: 60%
retail[index,]