Tibbles

“tibbles” adalah data frame, tetapi di tweak agar make life a little easier. Kalau di buku ini bilang kenapa pakai tibble instead yang lain, karena agar kita menggunakan library tidyverse lebih mudah.

Creating tibbles

Semisal kalau kita sudah punya data terus ingin kita convert jadi tibble cukup gunakan as_tibble()

as_tibble(iris)
## # A tibble: 150 × 5
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
##           <dbl>       <dbl>        <dbl>       <dbl> <fct>  
##  1          5.1         3.5          1.4         0.2 setosa 
##  2          4.9         3            1.4         0.2 setosa 
##  3          4.7         3.2          1.3         0.2 setosa 
##  4          4.6         3.1          1.5         0.2 setosa 
##  5          5           3.6          1.4         0.2 setosa 
##  6          5.4         3.9          1.7         0.4 setosa 
##  7          4.6         3.4          1.4         0.3 setosa 
##  8          5           3.4          1.5         0.2 setosa 
##  9          4.4         2.9          1.4         0.2 setosa 
## 10          4.9         3.1          1.5         0.1 setosa 
## # ℹ 140 more rows

Atau semisal kalau ingin membuatnya dari scratch, kita bisa menggunakan tibble()

tibble(
  x = 1:5,
  y = 1,
  z = x ^ 2 + y
)
## # A tibble: 5 × 3
##       x     y     z
##   <int> <dbl> <dbl>
## 1     1     1     2
## 2     2     1     5
## 3     3     1    10
## 4     4     1    17
## 5     5     1    26

Lalu menariknya adalah perbedaan dari data.frame() daripada tibble() adalah tibble tidak pernah mengubah tipe data dari input (e.g. tidak pernah converts string menjadi factors), tidak pernah mengganti nama variables nya, dan tidak pernah membuat row names (?)

Lalu pada tibble kita bisa membuat nama columns dengan nama yang nyeleneh atau non-syntatic names

tb <- tibble(
  `:)` = "smile", 
  ` ` = "space",
  `2000` = "number"
)
tb
## # A tibble: 1 × 3
##   `:)`  ` `   `2000`
##   <chr> <chr> <chr> 
## 1 smile space number

Lalu ada juga yang namanya tribble() yaitu transposed tibble merupakan customised untuk data entry. ex:

tribble(
  ~x, ~y, ~z,
  #--|--|----
  "a", 2, 3.6,
  "b", 1, 8.5
)
## # A tibble: 2 × 3
##   x         y     z
##   <chr> <dbl> <dbl>
## 1 a         2   3.6
## 2 b         1   8.5

Tibbles vs data.frame

Ada dua perbedaan antara tibble vs data.frame yaitu: printing dan subsetting

Printing

Kalau pake tibble hanya mengeluarkan output 10 rows pertama dan menampilkan seluruh columns yang fit on screen. Yang dimana ini berguna ketika kita memiliki data yang besar.

tibble(
  a = lubridate::now() + runif(1e3) * 86400,
  b = lubridate::today() + runif(1e3) * 30,
  c = 1:1e3,
  d = runif(1e3),
  e = sample(letters, 1e3, replace = TRUE)
)
## # A tibble: 1,000 × 5
##    a                   b              c      d e    
##    <dttm>              <date>     <int>  <dbl> <chr>
##  1 2023-05-02 05:04:29 2023-05-05     1 0.0295 g    
##  2 2023-05-02 12:30:32 2023-05-23     2 0.901  k    
##  3 2023-05-02 09:17:19 2023-05-16     3 0.0859 k    
##  4 2023-05-01 20:22:51 2023-05-05     4 0.123  e    
##  5 2023-05-02 15:05:13 2023-05-26     5 0.641  s    
##  6 2023-05-02 02:31:41 2023-05-10     6 0.974  g    
##  7 2023-05-01 22:36:03 2023-05-29     7 0.562  q    
##  8 2023-05-02 14:18:56 2023-05-17     8 0.328  g    
##  9 2023-05-02 04:53:03 2023-05-07     9 0.572  i    
## 10 2023-05-02 18:07:59 2023-05-12    10 0.571  t    
## # ℹ 990 more rows

Alasan kenapa tibbles dibuat adalah agar kita tidak overwhelm dengan output di console ketika kita print data frames yang besar!!!

Sebenernya kita bisa mainkan parameter pada tibble untuk nge output jumlah baris dan kolom nya berapa

Atau, kita bisa menggunakan function View()

nycflights13::flights %>%
  View()

Subsetting

Jika kita ingin extract data / value dari single variable atau column, kita bisa menggunakan $ dan [[. Perbedaannya [[ bisa extract by name atau position sedangkan $ hanya bisa extract by name. Contoh:

df <- tibble(
  x = runif(5),
  y = rnorm(5)
)

# Extract by name using dollar sign
df$x
## [1] 0.4689837 0.3907106 0.6622299 0.3303831 0.5590671
# Extract by name using bracket kotak
df[["x"]]
## [1] 0.4689837 0.3907106 0.6622299 0.3303831 0.5590671
# Extract by position
df[[1]]
## [1] 0.4689837 0.3907106 0.6622299 0.3303831 0.5590671

Kita juga bisa menggunakan pipe ketika extract data, cukup menggunakan special placeholder .

df %>% .$x
## [1] 0.4689837 0.3907106 0.6622299 0.3303831 0.5590671
df %>% .[["x"]]
## [1] 0.4689837 0.3907106 0.6622299 0.3303831 0.5590671

Data Import

Untuk melakukan read data, kita bisa menggunakan library readr yang merupakan core dari library tidyverse.

Function read data yang paling sering digunakan di R adalah:

heights <- read_csv(<PATH_TO_FILE>)

Kita juga bisa langsung menggunakan read_csv() untuk inline csv file

read_csv("a,b,c
1,2,3
4,5,6")
## Rows: 2 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (3): a, b, c
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## # A tibble: 2 × 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     6

Selain itu, jika kita memiliki data yang tidak memiliki columns name kita bisa langsung pass cols name nya di read_csv()

read_csv("1,2,3\n4,5,6", col_names = c("x", "y", "z"))
## Rows: 2 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (3): x, y, z
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## # A tibble: 2 × 3
##       x     y     z
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     6

Parsing Data Types (Vector)

Tujuan menggunakan parser adalah untuk kita convert data atau deal with different data types of input ke dalam bentuk yang kita inginkan. Parser yang sering digunakan di R:

parse_double("1.23")
## [1] 1.23
parse_double("1,23", locale = locale(decimal_mark = ","))
## [1] 1.23
parse_number("$100")
## [1] 100
parse_number("20%")
## [1] 20
parse_number("It cost $123.45")
## [1] 123.45
parse_datetime("2010-10-01T2010")
## [1] "2010-10-01 20:10:00 UTC"
# If time is omitted, it will be set to midnight
parse_datetime("20101010")
## [1] "2010-10-10 UTC"
parse_date("2010-10-01")
## [1] "2010-10-01"
library(hms)
## 
## Attaching package: 'hms'
## The following object is masked from 'package:lubridate':
## 
##     hms
parse_time("01:10 am")
## 01:10:00
parse_time("20:10:01")
## 20:10:01

Writing to a file

Untuk save data yang setelah kita olah, kita bisa simpan dalam bentuk .csv atau .tsv. Kita bisa menggunakan function write_csv()

write_csv(<NAMA_VAR_DATA>, <OUTPUT_NAME_FILE.csv>)

Other types of data

Selain data yang sudah disebutkan di section atas, sebenarnya masih banyak data yang bisa digunakan di R, contohnya:

  • haven untuk membaca SPSS, Stata, dan SAS

  • readxl untuk membaca file excel

  • DBI untuk membaca database seperti RMySQL, RSQLite, RPostreSQL, dll

  • jsonlite

  • xml2

Tidy Data

Tidy data adalah sebuah proses membuat data kita menjadi bentuk yang konsisten dan lebih terorganisir. Tetapi proses ini itu membutuhkan effort.

Jika ingin membaca lebih detail tentang underlying theory dari Tidy Data bisa baca di link berikut

Terdapat “rules” untuk membuat dataset tidy:

  1. Each variables must have its own column

  2. Each observation must have its own row

  3. Each value must have its own cell

Case Study Tidy Data

Nanti kasih github nya

Relational Data

Multiple tables of data itu disebut dengan relational data. Bentuk umum dari relational data adalah RDBMS.

Tentu karena kita membahas tentang Relational data, maka akan ada komponen Keys. Bentuk dari keys adalah:

Mutating joins

Join merupakan komponen yang penting dari relational data, karena kita bisa melakukan combine data dengan antar tabel. Join yang dipakai di R adalah:

  • Left Join

  • Right Join

  • Inner Join

  • Full Join

Strings

Pada chapter ini akan belajar tentang basics string bekerja, bagaimana cara membuatnya, dan string manipulation.

String basics

Untuk cara membuat string cukup simple, kita bisa menggunakan single quotes ' atau double quotes "

string1 <- "This is a string"
string2 <- 'If I want to include a "quote" inside a string, I use single quotes'

String length

Untuk mengecek panjang dari sebuah strings, kita bisa menggunakan str_length()

str_length(c("a", "R for data science", NA))
## [1]  1 18 NA

Combining strings

Untuk combine dua atau lebih strings, bisa menggunakan str_c()

str_c("R", "for", "Data", "Science", sep = " ")
## [1] "R for Data Science"

Subsetting string

Kita juga bisa melakukan extract which parts of string menggunakan str_sub()

x <- c("Apple", "Banana", "Pear")
str_sub(x, 1, 3)
## [1] "App" "Ban" "Pea"
# negative numbers count backwards from end
str_sub(x, -3, -1)
## [1] "ple" "ana" "ear"

Terus pada buku ini pada string nya, mainly akan bahas tentang regex manipulation. Tapi itu takes time, jadi di skip terlebih dahulu.

Factors

Factors digunakan untuk categorical variables, yang dimana nilai nya udah fixed dan known set of possible values. Biasanya akan kepakai ketika kita akan membuat data Survey.

Data yang yang categorical (nominal) dan ordered categorical (ordinal). Sehingga kita bisa melakukan ordering

Membuat factors

Semisal kita mau membuat variable untuk menyimpan month

x1 <- c("Dec", "Apr", "Jan", "Mar")

Tetapi tidak bisa kita sort data nya sesuai dengan keinginan kita

sort(x1)
## [1] "Apr" "Dec" "Jan" "Mar"

Maka, kita bisa fix problem tersebut menggunakan factor. Untuk membuat factor, kita bisa mengguakan list of the valid levels:

month_levels <- c(
  "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
)

Lalu, kita tinggal membuat factor

y1 <- factor(x1, levels = month_levels)

sort(y1)
## [1] Jan Mar Apr Dec
## Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec

Dates and times

Creating date/times

Terdapat tiga tipe date/time:

  • date. Tibble akan print sebagai <date>

  • time within a day. Tibbel akan print sebagai <time>

  • date-time merupakan date plus a time. Tibble akan print sebagai <dttm>

Kita bisa dapetin current date or date-time menggunakan today() atau now()

today()
## [1] "2023-05-01"
now()
## [1] "2023-05-01 19:15:35 WIB"

Kita juga bisa membuat date/time dengan cara:

  • From a string

  • From individual date-time components

  • From an existing date/time object

From string

Kita tinggal arange “y”, “m”, dan “d” sesuai dengan order yang kita inginkan

ymd("2017-01-31")
## [1] "2017-01-31"
mdy("January 31st, 2017")
## [1] "2017-01-31"
dmy("31-Jan-2017")
## [1] "2017-01-31"
ymd(20170131)
## [1] "2017-01-31"

Selain menggunakan date, kita juga bisa menggunakan date-time. Untuk parsing nya kita tinggal tambahkan “h”, “m”, “s”. Untuk default nya akan ter-parsing ke dalam bentuk UTC

ymd_hms("2017-01-31 20:11:59")
## [1] "2017-01-31 20:11:59 UTC"
mdy_hm("01/31/2017 08:01")
## [1] "2017-01-31 08:01:00 UTC"

From individual components

Kita juga bisa membuat date-time dari data yang terdapat dari multiple columns. Contoh kita akan menggunakan data flights dan kita bisa menggunakan make_date() untuk membuat date dan make_datetime() untuk membuat date-times

flights %>%
  select(year, month, day, hour, minute) %>%
  mutate(departure = make_datetime(year, month, day, hour, minute))
## # A tibble: 336,776 × 6
##     year month   day  hour minute departure          
##    <int> <int> <int> <dbl>  <dbl> <dttm>             
##  1  2013     1     1     5     15 2013-01-01 05:15:00
##  2  2013     1     1     5     29 2013-01-01 05:29:00
##  3  2013     1     1     5     40 2013-01-01 05:40:00
##  4  2013     1     1     5     45 2013-01-01 05:45:00
##  5  2013     1     1     6      0 2013-01-01 06:00:00
##  6  2013     1     1     5     58 2013-01-01 05:58:00
##  7  2013     1     1     6      0 2013-01-01 06:00:00
##  8  2013     1     1     6      0 2013-01-01 06:00:00
##  9  2013     1     1     6      0 2013-01-01 06:00:00
## 10  2013     1     1     6      0 2013-01-01 06:00:00
## # ℹ 336,766 more rows

Untuk next nya kita akan menggunakan data berikut

# function create datetime

make_datetime_100 <- function(year, month, day, time) {
  make_datetime(year, month, day, time %/% 100, time %% 100)
}

flights_dt <- flights %>%
  filter(!is.na(dep_time), !is.na(arr_time)) %>%
  mutate(
    dep_time = make_datetime_100(year, month, day, dep_time),
    arr_time = make_datetime_100(year, month, day, arr_time),
    sched_dep_time = make_datetime_100(year, month, day, sched_dep_time),
    sched_arr_time = make_datetime_100(year, month, day, sched_arr_time)
  ) %>%
  select(origin, dest, ends_with("delay"), ends_with("time"))

flights_dt
## # A tibble: 328,063 × 9
##    origin dest  dep_delay arr_delay dep_time            sched_dep_time     
##    <chr>  <chr>     <dbl>     <dbl> <dttm>              <dttm>             
##  1 EWR    IAH           2        11 2013-01-01 05:17:00 2013-01-01 05:15:00
##  2 LGA    IAH           4        20 2013-01-01 05:33:00 2013-01-01 05:29:00
##  3 JFK    MIA           2        33 2013-01-01 05:42:00 2013-01-01 05:40:00
##  4 JFK    BQN          -1       -18 2013-01-01 05:44:00 2013-01-01 05:45:00
##  5 LGA    ATL          -6       -25 2013-01-01 05:54:00 2013-01-01 06:00:00
##  6 EWR    ORD          -4        12 2013-01-01 05:54:00 2013-01-01 05:58:00
##  7 EWR    FLL          -5        19 2013-01-01 05:55:00 2013-01-01 06:00:00
##  8 LGA    IAD          -3       -14 2013-01-01 05:57:00 2013-01-01 06:00:00
##  9 JFK    MCO          -3        -8 2013-01-01 05:57:00 2013-01-01 06:00:00
## 10 LGA    ORD          -2         8 2013-01-01 05:58:00 2013-01-01 06:00:00
## # ℹ 328,053 more rows
## # ℹ 3 more variables: arr_time <dttm>, sched_arr_time <dttm>, air_time <dbl>

Enaknya menggunakan data datetime kita bisa melakukan visualisasi

flights_dt %>%
  ggplot(aes(dep_time)) +
  geom_freqpoly(binwidth = 86400) # 86400 seconds = 1 day

Kita juga bisa mengambil data per day nya

flights_dt %>%
  filter(dep_time < ymd(20130102)) %>%
  ggplot(aes(dep_time)) +
  geom_freqpoly(binwidth = 600) # 600 s = 10 minutes

From other types

Kita juga bisa melakukan switch antara date-time dan date, bisa mengguanakan as_datetime() dan as_date()

as_datetime(today())
## [1] "2023-05-01 UTC"
as_date(now())
## [1] "2023-05-01"

Getting components

Kita bisa mengambil individual komponen menggunakan year(), month(), mday() (day of the month), yday() (day of the year), wday() (day of the week), hour(), minute(), dan second()

Semisal kita ingin mengambil flights depart during the week

flights_dt %>%
  mutate(wday = wday(dep_time, label = TRUE)) %>%
  ggplot(aes(x = wday)) +
    geom_bar()

Ternyata kita bisa menemukan pattern yang menarik jika kita melihat average departure delay by minute with the hours. Ternyata flights yang terbang di minutes 20-30 dan 50-60 memiliki nilai lower delays daripada yang lain!!!

flights_dt %>%
  mutate(minute = minute(dep_time)) %>%
  group_by(minute) %>%
  summarise(
    avg_delay = mean(arr_delay, na.rm = TRUE),
    n = n()) %>%
  ggplot(aes(minute, avg_delay)) +
    geom_line()

Rounding

Pada datetime kita juga bisa menggunakan rounding ke nearby unit of time, function nya floor_date(), round_date(), dan ceiling_date(). Kalau round down pakai “floor”, sedangkan round up pakai “ceiling”.

Time spans

Kita juga bisa melakukan arithmetic pada dates, mulai dari subtraction, addition, dan division. Kita bisa menggunakan tiga komponen/classes yang merepresentasikan time spans:

  • durations, represent an exact number of seconds

  • periods, represent human units like weeks and months

  • intervals, represent a starting and ending point

Ex:

# How old is Hadley?
h_age <- today() - ymd(19791014)

h_age
## Time difference of 15905 days