Wrangle

readr

Disini saya akan mencoba belajar tentang “Data Wrangling”. “Data Wrangling” adalah suatu usaha agar data yang saya miliki menjadi bentuk yang dapat digunakan/berguna untuk melakukan “vizualitation” dan “modelling”. Pada bagian ini saya akan belajar tentang membaca data menggunakan readr.

library(tidyverse)

Pendahuluan

Load files in R

Ketika saya menjalankan “read_csv”, ketika itu juga akan ditampilkan spesifikasi colom/variabel seperti nama dan tipe data.

a<-read_csv("Data.csv")
## Parsed with column specification:
## cols(
##   Country = col_character(),
##   Age = col_double(),
##   Salary = col_double(),
##   Purchased = col_character()
## )
read_csv("1,2,3\n4,5,7", col_names = F)
## # A tibble: 2 x 3
##      X1    X2    X3
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     7
read_csv("1,2,3\n4,5,7", col_names = c("a","b","c"))
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     7
read_csv("1,2,3\n4,5,.", na=".", col_names = F)
## # A tibble: 2 x 3
##      X1    X2    X3
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5    NA

saya juga dapat membaca data yang dituliskan “inline” dalam R.

read_csv("a, b,c
         1,2,3
         7,8,9")
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     7     8     9

Apabila dalam “inline”(penulisan data pada R) terdapat kalimat, judul atau suatu string yang bukan “data” (seperti dibawah). Hal tersebut dapat teratasi dengan “skip” atau“comment”

read_csv("data
         adalah
         a,b,c
         1,2,3")
## Warning: 2 parsing failures.
## row col  expected    actual         file
##   2  -- 1 columns 3 columns literal data
##   3  -- 1 columns 3 columns literal data
## # A tibble: 3 x 1
##   data  
##   <chr> 
## 1 adalah
## 2 a     
## 3 1
read_csv("1,2,3\n4,5,7", col_names = F)
## # A tibble: 2 x 3
##      X1    X2    X3
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     7
read_csv("1,2,3\n4,5,7", col_names = c("a","b","c"))
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     7
read_csv("1,2,3\n4,5,.", na=".", col_names = F)
## # A tibble: 2 x 3
##      X1    X2    X3
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5    NA
# skip
read_csv("data
         adalah
         a,b,c
         1,2,3", skip=2)
## # A tibble: 1 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
# comment
read_csv("#data
          #adalah
         a,b,c
         7,8,9", comment="#")
## # A tibble: 2 x 3
##   a     b     c    
##   <chr> <chr> <chr>
## 1 a     b     c    
## 2 7     8     9

Parsing a Vector

Sebelum mengetahui tentang detail dari readr, saya harus memahami dulu tentang parse.

a character vector to parse

str(parse_logical(c("True", "False","False")))
##  logi [1:3] TRUE FALSE FALSE
str(parse_integer(c("1","2","33")))
##  int [1:3] 1 2 33
str(parse_date(c("2010-01-01","1999-05-29")))
##  Date[1:2], format: "2010-01-01" "1999-05-29"
parse_integer(c("1","2","33","."), na=".")
## [1]  1  2 33 NA

Apabila “parsing” gagal, akan muncul “warning” seperti berikut.

salah<-parse_integer(c("1","2","3.3","aca"))
## Warning: 2 parsing failures.
## row col               expected actual
##   3  -- no trailing characters    .3 
##   4  -- an integer                aca

Apabila banyak “parsing” gagal maka gunakan “problems()” untuk mendapatkan keseluruhan set.

problems(salah)
## # A tibble: 2 x 4
##     row   col expected               actual
##   <int> <int> <chr>                  <chr> 
## 1     3    NA no trailing characters .3    
## 2     4    NA an integer             aca

Parsing a Number

Permasalahan pada “parsing a number” adalah

  1. perbedaan dalam menulis decimal, beberapa menggunakan “.” beberapa lain menggunakan “,”.

  2. terdapat carakter pada penulisan, seperti “30%”, “4$”.

  3. penulisan seperti “1,000,000” untuk memudahkan membaca namun pada pengolahan data menjadi suatu permasalahan.

# parsing a number secara default membaca "." sebagai decimal
parse_double("1.23")
## [1] 1.23
# apabila mengubah tanda decimal menjadi ","
parse_double("1,23", locale = locale(decimal_mark = ","))
## [1] 1.23
# parse a number secara default hanya membaca nomer
parse_number("123adalah")
## [1] 123
parse_number("123,98")
## [1] 12398
parse_number("adalah123.980%")
## [1] 123.98
# apabila penulisan seperti "1,000,000" gunakan locale = locale(grouping_mark = "," untuk menanganinya
parse_number("adalah123.000.000", locale = locale(grouping_mark = "."))
## [1] 1.23e+08
parse_number("adalah123,000,000", locale = locale(grouping_mark = ","))
## [1] 1.23e+08

Parsing a Strings

Pada bagian ini saya bingung, larinya ke encoding seperti ASCII dll.

charToRaw("Hadley") 
## [1] 48 61 64 6c 65 79
x1<-"El Ni\xf1o was particulary bad this year"
x2<-"\x82\xb1\x82\xf1\x82\xbf\x82\xcd"
parse_character(x1, locale = locale(encoding = "Latin1"))
## [1] "El Niño was particulary bad this year"
parse_character(x2, locale = locale(encoding = "Shift-JIS"))
## [1] "<U+3053><U+3093><U+3061><U+306F>"
guess_encoding(charToRaw(x1))
## # A tibble: 2 x 2
##   encoding   confidence
##   <chr>           <dbl>
## 1 ISO-8859-1       0.47
## 2 ISO-8859-9       0.23
guess_encoding(charToRaw(x2))
## # A tibble: 0 x 2
## # ... with 2 variables: encoding <chr>, confidence <dbl>

Parsing a Factors

contoh dibawah ini, saya mempunyai factor/kategori apel dan pisang. Apabila saya “parsing” apel dan pisang pada factor, bener. Tapi apabila Apabila saya “parsing” apel, pisang dan anggur pada factor muncul “warning”. Hal ini karena anggur bukan bagian pada factor apalagi nganggur :( .

fruit<-c("apel","pisang")
parse_factor(c("apel", "pisang"), levels = fruit)
## [1] apel   pisang
## Levels: apel pisang
parse_factor(c("apel", "pisang", "anggur"), levels = fruit)
## Warning: 1 parsing failure.
## row col           expected actual
##   3  -- value in level set anggur
## [1] apel   pisang <NA>  
## attr(,"problems")
## # A tibble: 1 x 4
##     row   col expected           actual
##   <int> <int> <chr>              <chr> 
## 1     3    NA value in level set anggur
## Levels: apel pisang
da<-parse_factor(c("apel", "pisang", "anggur"), levels = fruit)
## Warning: 1 parsing failure.
## row col           expected actual
##   3  -- value in level set anggur
problems(da)
## # A tibble: 1 x 4
##     row   col expected           actual
##   <int> <int> <chr>              <chr> 
## 1     3    NA value in level set anggur

Parsing a Dates

Keterangan : %Y (4 digits), %y (2 digits), %m (2 digits), %b (singkatan seperti Jan), %B (nama bulan seperti Januari), %d (2 digits), %H (24 jam), %M (menit), %S (detik), %OS (detik bilangan real), %Z (zona waktu), %z (UTc)

parse_datetime("2010-10-01T2010")
## [1] "2010-10-01 20:10:00 UTC"
parse_datetime("20101001")
## [1] "2010-10-01 UTC"
parse_date("2010-10-01")
## [1] "2010-10-01"
parse_time("13/01/12.45","%H/%M/%OS")
## 13:01:12.45
parse_date("01/02/20","%m/%d/%y")
## [1] "2020-01-02"

Parsing a File

best guess parser

Pada vektor karakter gunakan guess_parser dan pada kolom gunakan parse_guess

guess_parser("2010-02-08")
## [1] "date"
guess_parser("15:20")
## [1] "time"
guess_parser(c("1","5","9"))
## [1] "double"
str(parse_guess("2010-02-08"))
##  Date[1:1], format: "2010-02-08"
str(parse_guess(c("True","False","False")))
##  logi [1:3] TRUE FALSE FALSE

Contoh data set dibawah, terlihat terdapat 1000 kesalahan parsing. Menggunakan problems kita dapat keseluruhan kesalahan parsing.

challenge<-read_csv(readr_example("challenge.csv"))
## Parsed with column specification:
## cols(
##   x = col_double(),
##   y = col_logical()
## )
## Warning: 1000 parsing failures.
##  row col           expected     actual                                                                    file
## 1001   y 1/0/T/F/TRUE/FALSE 2015-01-16 'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1002   y 1/0/T/F/TRUE/FALSE 2018-05-18 'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1003   y 1/0/T/F/TRUE/FALSE 2015-09-05 'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1004   y 1/0/T/F/TRUE/FALSE 2012-11-28 'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1005   y 1/0/T/F/TRUE/FALSE 2020-01-13 'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## .... ... .................. .......... .......................................................................
## See problems(...) for more details.
problems(challenge)
## # A tibble: 1,000 x 5
##      row col   expected       actual   file                                     
##    <int> <chr> <chr>          <chr>    <chr>                                    
##  1  1001 y     1/0/T/F/TRUE/~ 2015-01~ 'C:/Users/asus/Documents/R/win-library/4~
##  2  1002 y     1/0/T/F/TRUE/~ 2018-05~ 'C:/Users/asus/Documents/R/win-library/4~
##  3  1003 y     1/0/T/F/TRUE/~ 2015-09~ 'C:/Users/asus/Documents/R/win-library/4~
##  4  1004 y     1/0/T/F/TRUE/~ 2012-11~ 'C:/Users/asus/Documents/R/win-library/4~
##  5  1005 y     1/0/T/F/TRUE/~ 2020-01~ 'C:/Users/asus/Documents/R/win-library/4~
##  6  1006 y     1/0/T/F/TRUE/~ 2016-04~ 'C:/Users/asus/Documents/R/win-library/4~
##  7  1007 y     1/0/T/F/TRUE/~ 2011-05~ 'C:/Users/asus/Documents/R/win-library/4~
##  8  1008 y     1/0/T/F/TRUE/~ 2020-07~ 'C:/Users/asus/Documents/R/win-library/4~
##  9  1009 y     1/0/T/F/TRUE/~ 2011-04~ 'C:/Users/asus/Documents/R/win-library/4~
## 10  1010 y     1/0/T/F/TRUE/~ 2010-05~ 'C:/Users/asus/Documents/R/win-library/4~
## # ... with 990 more rows

Pertama saya coba ganti kolom x menjadi integer, dan kolom y menjadi karakter. Eh loh masih “warning” berarti parsing gagal lagi.

read_csv(readr_example("challenge.csv"), col_types = cols(x=col_integer(),
                                                              y=col_character()))
## Warning: 1000 parsing failures.
##  row col               expected             actual                                                                    file
## 1001   x no trailing characters .23837975086644292 'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1002   x no trailing characters .41167997173033655 'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1003   x no trailing characters .7460716762579978  'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1004   x no trailing characters .723450553836301   'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## 1005   x no trailing characters .614524137461558   'C:/Users/asus/Documents/R/win-library/4.0/readr/extdata/challenge.csv'
## .... ... ...................... .................. .......................................................................
## See problems(...) for more details.
## # A tibble: 2,000 x 2
##        x y    
##    <int> <chr>
##  1   404 <NA> 
##  2  4172 <NA> 
##  3  3004 <NA> 
##  4   787 <NA> 
##  5    37 <NA> 
##  6  2332 <NA> 
##  7  2489 <NA> 
##  8  1449 <NA> 
##  9  3665 <NA> 
## 10  3863 <NA> 
## # ... with 1,990 more rows

Kedua saya coba ganti kolom x menjadi double, dan kolom y menjadi karakter (bener, gak ada “warning”). Tapi eh waktu diliat data terakhir kolom y kaya tanggal, coba.

read_csv(readr_example("challenge.csv"), col_types = cols(x=col_double(),
                                                              y=col_character()))
## # A tibble: 2,000 x 2
##        x y    
##    <dbl> <chr>
##  1   404 <NA> 
##  2  4172 <NA> 
##  3  3004 <NA> 
##  4   787 <NA> 
##  5    37 <NA> 
##  6  2332 <NA> 
##  7  2489 <NA> 
##  8  1449 <NA> 
##  9  3665 <NA> 
## 10  3863 <NA> 
## # ... with 1,990 more rows
c1<-read_csv(readr_example("challenge.csv"), col_types = cols(x=col_double(),
                                                              y=col_character()))
tail(c1)
## # A tibble: 6 x 2
##       x y         
##   <dbl> <chr>     
## 1 0.805 2019-11-21
## 2 0.164 2018-03-29
## 3 0.472 2014-08-04
## 4 0.718 2015-08-16
## 5 0.270 2020-02-04
## 6 0.608 2019-01-06

Eh, lah iya bener.

read_csv(readr_example("challenge.csv"), col_types = cols(x=col_double(),
                                                              y=col_date()))
## # A tibble: 2,000 x 2
##        x y         
##    <dbl> <date>    
##  1   404 NA        
##  2  4172 NA        
##  3  3004 NA        
##  4   787 NA        
##  5    37 NA        
##  6  2332 NA        
##  7  2489 NA        
##  8  1449 NA        
##  9  3665 NA        
## 10  3863 NA        
## # ... with 1,990 more rows
c1<-read_csv(readr_example("challenge.csv"), col_types = cols(x=col_double(),
                                                              y=col_date()))
tail(c1)
## # A tibble: 6 x 2
##       x y         
##   <dbl> <date>    
## 1 0.805 2019-11-21
## 2 0.164 2018-03-29
## 3 0.472 2014-08-04
## 4 0.718 2015-08-16
## 5 0.270 2020-02-04
## 6 0.608 2019-01-06

Cara lain

# melihat idealnya data merupakan parsing mana (mengecek dari data 1:1400)
c2<-read_csv(readr_example("challenge.csv"),guess_max = 1400)
## Parsed with column specification:
## cols(
##   x = col_double(),
##   y = col_date(format = "")
## )
# nah tinggal ganti
c2<-read_csv(readr_example("challenge.csv"), col_types = cols(x=col_double(),
                                                              y=col_date()))
c2
## # A tibble: 2,000 x 2
##        x y         
##    <dbl> <date>    
##  1   404 NA        
##  2  4172 NA        
##  3  3004 NA        
##  4   787 NA        
##  5    37 NA        
##  6  2332 NA        
##  7  2489 NA        
##  8  1449 NA        
##  9  3665 NA        
## 10  3863 NA        
## # ... with 1,990 more rows

cara lebih bagus jadi karakter semua lalu convert.

c3<-read_csv(readr_example("challenge.csv"), col_types = cols(.default = col_character()))
c3
## # A tibble: 2,000 x 2
##    x     y    
##    <chr> <chr>
##  1 404   <NA> 
##  2 4172  <NA> 
##  3 3004  <NA> 
##  4 787   <NA> 
##  5 37    <NA> 
##  6 2332  <NA> 
##  7 2489  <NA> 
##  8 1449  <NA> 
##  9 3665  <NA> 
## 10 3863  <NA> 
## # ... with 1,990 more rows
type_convert(c3)
## Parsed with column specification:
## cols(
##   x = col_double(),
##   y = col_date(format = "")
## )
## # A tibble: 2,000 x 2
##        x y         
##    <dbl> <date>    
##  1   404 NA        
##  2  4172 NA        
##  3  3004 NA        
##  4   787 NA        
##  5    37 NA        
##  6  2332 NA        
##  7  2489 NA        
##  8  1449 NA        
##  9  3665 NA        
## 10  3863 NA        
## # ... with 1,990 more rows

Writing to a File

# type information hilang, balik ke awal
write_csv(c2, "challenge.csv" )
read_csv("challenge.csv")
## # A tibble: 2,000 x 2
##        x y    
##    <dbl> <lgl>
##  1   404 NA   
##  2  4172 NA   
##  3  3004 NA   
##  4   787 NA   
##  5    37 NA   
##  6  2332 NA   
##  7  2489 NA   
##  8  1449 NA   
##  9  3665 NA   
## 10  3863 NA   
## # ... with 1,990 more rows
#cocok
write_rds(c2, "challenge2.csv")
read_rds("challenge2.csv")
## # A tibble: 2,000 x 2
##        x y         
##    <dbl> <date>    
##  1   404 NA        
##  2  4172 NA        
##  3  3004 NA        
##  4   787 NA        
##  5    37 NA        
##  6  2332 NA        
##  7  2489 NA        
##  8  1449 NA        
##  9  3665 NA        
## 10  3863 NA        
## # ... with 1,990 more rows
# dapat dishare dengan bahasa pemprograman lain
library(feather)
write_feather(c2,"challenge3.feather")
read_feather("challenge3.feather")
## # A tibble: 2,000 x 2
##        x y         
##    <dbl> <date>    
##  1   404 NA        
##  2  4172 NA        
##  3  3004 NA        
##  4   787 NA        
##  5    37 NA        
##  6  2332 NA        
##  7  2489 NA        
##  8  1449 NA        
##  9  3665 NA        
## 10  3863 NA        
## # ... with 1,990 more rows