library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.2.2
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.3.6 ✔ purrr 0.3.5
## ✔ tibble 3.1.8 ✔ dplyr 1.0.10
## ✔ tidyr 1.2.1 ✔ stringr 1.4.1
## ✔ readr 2.1.4 ✔ forcats 0.5.2
## Warning: package 'readr' was built under R version 4.2.3
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
library(nycflights13)
## Warning: package 'nycflights13' was built under R version 4.2.3
library(Lahman)
## Warning: package 'Lahman' was built under R version 4.2.3
Seringkali perlu menggunakan variabel dalam kumpulan data untuk
membuat variabel baru. Fungsi transformasi yang digunakan untuk
melakukan ini adalah mutate.
Misalnya, kita mungkin ingin menambahkan kolom yang
flightsberisi kecepatan udara rata-rata setiap penerbangan.
Mengingat bahwa kecepatan rata-rata adalah jarak total dibagi waktu
total, kita dapat menghitung kecepatan udara penerbangan dengan
menghitung distance / air_time. Hampir saja. Satuannya
distanceadalah mil, dan satuannya
air_timeadalah menit, jadi untuk menghitung kecepatan udara
dalam satuan mil per jam yang lebih familiar, kita sebenarnya ingin
menghitung distance / air_time * 60.
Untuk membuat perhitungan ini untuk setiap baris
flightsdan menambahkannya sebagai kolom baru (sebut saja
kolom baru ini air_speed), kami menerapkan
mutatefungsi sebagai berikut:
flights %>%
mutate(air_speed = distance / air_time * 60)
## # A tibble: 336,776 × 20
## year month day dep_time sched_de…¹ dep_d…² arr_t…³ sched…⁴ arr_d…⁵ carrier
## <int> <int> <int> <int> <int> <dbl> <int> <int> <dbl> <chr>
## 1 2013 1 1 517 515 2 830 819 11 UA
## 2 2013 1 1 533 529 4 850 830 20 UA
## 3 2013 1 1 542 540 2 923 850 33 AA
## 4 2013 1 1 544 545 -1 1004 1022 -18 B6
## 5 2013 1 1 554 600 -6 812 837 -25 DL
## 6 2013 1 1 554 558 -4 740 728 12 UA
## 7 2013 1 1 555 600 -5 913 854 19 B6
## 8 2013 1 1 557 600 -3 709 723 -14 EV
## 9 2013 1 1 557 600 -3 838 846 -8 B6
## 10 2013 1 1 558 600 -2 753 745 8 AA
## # … with 336,766 more rows, 10 more variables: flight <int>, tailnum <chr>,
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## # minute <dbl>, time_hour <dttm>, air_speed <dbl>, and abbreviated variable
## # names ¹sched_dep_time, ²dep_delay, ³arr_time, ⁴sched_arr_time, ⁵arr_delay
Saat memutasi variabel baru ke kumpulan data, praktik yang lebih baik
adalah menetapkan nama baru untuk kumpulan data yang dimutasi. Anda
dapat melakukannya dengan memasukkan penetapan
nama <NEW NAME> <-di awal kode di atas:
flights_w_speed <- flights %>%
mutate(air_speed = distance / air_time * 60)
Anda sekarang dapat merujuk ke flights_w_speeduntuk
analisis selanjutnya.
Argumen dari mutateselalu berbentuk:
<NEW VARIABLE NAME> = <FORMULA INVOLVING OLD VARIABLES>
Rumusnya sering dibangun menggunakan aritmatika dasar, seperti perhitungan kecepatan udara di atas. Namun, ada baiknya menyebutkan beberapa operasi lain yang berguna untuk digunakan dalam rumus.
Jalankan baris kode berikut, dan coba tebak apa yang dilakukan
operator %/%and %%:
27 %/% 4
27 %% 4
Anda mungkin telah menebak bahwa %/%mengembalikan hasil
bagi bilangan bulat yang diperoleh saat membagi satu angka dengan angka
lainnya, sambil %%mengembalikan sisanya. Kita dapat
langsung melihat bagaimana operasi ini dapat diterapkan dengan melakukan
hal berikut: Tambahkan kolom yang flightsmenghitung jumlah
menit sejak tengah malam hingga setiap penerbangan berangkat dan kolom
lain yang menghitung jumlah menit sejak tengah malam hingga setiap
penerbangan tiba.
Misalnya, untuk penerbangan pertama dalam kumpulan data, nilai dari
dep_timeadalah 517, dan nilai dari
arr_timeadalah 830. Angka-angka ini sebenarnya hanyalah
singkatan dari 5:17am dan 8:30am, dan bukan angka yang bisa langsung
digunakan. dalam perhitungan. Mengubah waktu ini menjadi menit sejak
tengah malam akan memberikan pengukuran numerik aktual (bukan waktu)
yang menunjukkan kapan penerbangan berangkat atau tiba.
Untuk waktu keberangkatan 5:17, kita akan mengonversi ke menit sejak
tengah malam dengan menghitung 5*60 + 17, yaitu 317. Tapi
bagaimana kita memberitahu R untuk melakukan ini? Kami harus memiliki
cara untuk memisahkan satu atau dua digit pertama dari dua digit
terakhir. Di sinilah %/%dan %%masuk:
Perhatikan bahwa 517 %/% 100 = 5dan
517 %% 100 = 17. Dengan demikian, konversi dapat dilakukan
dengan rumus (517 %/% 100)*60 + (517 %% 100).
Kami sekarang dapat menambahkan menit kami sejak variabel tengah
malam sebagai berikut. (Perhatikan bahwa Anda dapat membuat lebih dari
satu variabel baru dalam satu mutatepanggilan.) Kami juga
akan memilih kolom yang relevan sehingga terlihat di output.
flights_w_mins_midnight <- flights %>%
mutate(dep_mins_midnight = (dep_time %/% 100)*60 + (dep_time %% 100),
arr_mins_midnight = (arr_time %/% 100)*60 + (arr_time %% 100)) %>%
select(dep_time, dep_mins_midnight, arr_time, arr_mins_midnight)
flights_w_mins_midnight
## # A tibble: 336,776 × 4
## dep_time dep_mins_midnight arr_time arr_mins_midnight
## <int> <dbl> <int> <dbl>
## 1 517 317 830 510
## 2 533 333 850 530
## 3 542 342 923 563
## 4 544 344 1004 604
## 5 554 354 812 492
## 6 554 354 740 460
## 7 555 355 913 553
## 8 557 357 709 429
## 9 557 357 838 518
## 10 558 358 753 473
## # … with 336,766 more rows
Operasi lain yang sangat berguna untuk digunakan
dalam mutaterumus
adalah ifelse. Fungsi ifelsemengembalikan
nilai yang bergantung pada kebenaran atau kepalsuan dari suatu
kondisi. Sintaks dasarnya adalah
ifelse(<CONDITION>,
<VALUE IF CONDITION IS TRUE>, <VALUE IF CONDITION IS FALSE)
Misalnya, di ifelsebawah ini mengatakan untuk memeriksa
apakah x < y. Jika ya, maka kembalikan
nilai x^2. Jika tidak, kembalikan string “halo”.
x <- 4
y <- 2
ifelse(x < y,
x^2,
"halo")
## [1] "halo"
ifelsepernyataan dapat digunakan di
dalam mutateuntuk membuat variabel baru dengan cara yang
bergantung pada kondisi pada variabel lama. Ini adalah cara yang sangat
berguna untuk mengkategorikan variabel kontinu, misalnya, untuk
menetapkan nilai kategorikal ke variabel kontinu. Misalnya, mungkin kita
ingin menambahkan kolom yang flightsmenyatakan apakah
penerbangan tiba terlambat atau tepat waktu (atau lebih awal). (Kami
hanya akan memilih kolom yang relevan untuk membuat kolom baru kami
terlihat.)
flights_w_arr_status <- flights %>%
mutate(arr_status = ifelse(arr_delay <= 0,
"on time",
"late")) %>%
select(month, day, arr_delay, origin, dest, arr_status)
flights_w_arr_status
## # A tibble: 336,776 × 6
## month day arr_delay origin dest arr_status
## <int> <int> <dbl> <chr> <chr> <chr>
## 1 1 1 11 EWR IAH late
## 2 1 1 20 LGA IAH late
## 3 1 1 33 JFK MIA late
## 4 1 1 -18 JFK BQN on time
## 5 1 1 -25 LGA ATL on time
## 6 1 1 12 EWR ORD late
## 7 1 1 19 EWR FLL late
## 8 1 1 -14 LGA IAD on time
## 9 1 1 -8 JFK MCO on time
## 10 1 1 8 LGA ORD late
## # … with 336,766 more rows
Pernyataan sederhana ifelseseperti di atas bekerja
dengan baik saat membuat variabel kategori biner (dua nilai) seperti
status kedatangan penerbangan. Namun, untuk membuat variabel kategorikal
dengan lebih dari dua kemungkinan nilai, ifelsetidaklah
ideal.
Misalkan kita ingin melakukan kembali kategorisasi di atas tetapi
dengan tambahan kategori “dibatalkan” untuk penerbangan dengan tanda
NAdi arr_delaykolom. Salah satu cara (tidak
optimal) untuk melakukan ini adalah dengan pernyataan bersarang
ifelse . Logikanya akan bekerja seperti ini: Pertama,
periksa apakah arr_delayitu NA. Jika ya, tetapkan nilai
“dibatalkan”. Jika tidak, maka kami belum siap untuk menetapkan nilai
karena masih bisa “tepat waktu” atau “terlambat”. Kami memiliki lebih
banyak pemeriksaan yang harus dilakukan. Jadi, dalam argumen ketiga kita
ifelse, kita harus memulai yang baru ifelse.
Ini baru ifelseakan memeriksa apakah
arr_delaynegatif atau 0. Jika ya, kami akan menetapkan
“tepat waktu”. Jika tidak, satu-satunya pilihan yang tersisa adalah
arr_delaypositif, jadi kami akan menetapkan “terlambat”.
Itufilterpada akhirnya adalah untuk memastikan bahwa nilai
“dibatalkan” benar-benar muncul di keluaran yang terlihat.
flights_w_arr_status2 <- flights %>%
mutate(arr_status = ifelse(is.na(arr_delay),
"canceled",
ifelse(arr_delay <= 0,
"on time",
"late"))) %>%
select(month, day, arr_delay, origin, dest, arr_status) %>%
filter(row_number() >= 611)
flights_w_arr_status2
## # A tibble: 336,166 × 6
## month day arr_delay origin dest arr_status
## <int> <int> <dbl> <chr> <chr> <chr>
## 1 1 1 46 JFK RSW late
## 2 1 1 -12 EWR PBI on time
## 3 1 1 3 LGA DTW late
## 4 1 1 -21 JFK PDX on time
## 5 1 1 68 LGA MIA late
## 6 1 1 NA LGA XNA canceled
## 7 1 1 -24 LGA MCO on time
## 8 1 1 66 JFK RDU late
## 9 1 1 -2 EWR MCO on time
## 10 1 1 27 JFK TPA late
## # … with 336,156 more rows
Ada beberapa masalah dengan ini, yang paling jelas adalah bahwa
ifelsepernyataan bersarang sulit dibaca, terutama bila ada
banyak kategori. (Di atas hanya memiliki tiga kategori dan sudah sangat
berantakan dengan tanda kurung.) Masalah lain adalah bahwa
ifelsepernyataan bersarang bergantung pada urutan
pemeriksaan kondisi. Salah satu latihan untuk bagian ini akan
mengilustrasikan apa yang terjadi jika kondisi NAdi atas
tidak diperiksa terlebih dahulu.
Ada opsi yang jauh lebih baik untuk kategorisasi dengan lebih dari
dua kategori: case_when. Begini cara kerjanya:
flights_w_arr_status3 <- flights %>%
mutate(arr_status = case_when(is.na(arr_delay) ~ "canceled",
arr_delay <= 0 ~ "on time",
arr_delay >0 ~ "late")) %>%
select(month, day, arr_delay, origin, dest, arr_status) %>%
filter(row_number() >= 611)
flights_w_arr_status3
## # A tibble: 336,166 × 6
## month day arr_delay origin dest arr_status
## <int> <int> <dbl> <chr> <chr> <chr>
## 1 1 1 46 JFK RSW late
## 2 1 1 -12 EWR PBI on time
## 3 1 1 3 LGA DTW late
## 4 1 1 -21 JFK PDX on time
## 5 1 1 68 LGA MIA late
## 6 1 1 NA LGA XNA canceled
## 7 1 1 -24 LGA MCO on time
## 8 1 1 66 JFK RDU late
## 9 1 1 -2 EWR MCO on time
## 10 1 1 27 JFK TPA late
## # … with 336,156 more rows