Tugas Sains Data - Combine Table dan Membuat Peta

DATABASE QUERY WITH R

Connection To Database

Kali ini contoh pemanggilan database akan menggunakan contoh data Northwind. Untuk dapat melakukannya, package DBI dan RSQLite perlu di-install terlebih dulu

Selanjutnya kita panggil package yang akan digunakan. Kita dapat memanggil package dplry dan dbplyr, atau bisa dengan hanya memanggil package tidyverse yang mencakup keduanya sekaligus. Selain itu, jangan lupa untuk memanggil package RSQLite dan DBI.

library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.0.5
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5     v purrr   0.3.4
## v tibble  3.1.0     v dplyr   1.0.7
## v tidyr   1.1.3     v stringr 1.4.0
## v readr   2.0.1     v forcats 0.5.1
## Warning: package 'ggplot2' was built under R version 4.0.5
## Warning: package 'tidyr' was built under R version 4.0.5
## Warning: package 'readr' was built under R version 4.0.5
## Warning: package 'purrr' was built under R version 4.0.5
## Warning: package 'dplyr' was built under R version 4.0.5
## Warning: package 'stringr' was built under R version 4.0.5
## Warning: package 'forcats' was built under R version 4.0.5
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(RSQLite)
## Warning: package 'RSQLite' was built under R version 4.0.5
library(DBI)
## Warning: package 'DBI' was built under R version 4.0.5

MENGGUNAKAN DATABASE NORTHWIND

Untuk menjalankan syntax berikut ini, maka perlu mengunduh Database Northwind_large.sqlite dan menyimpannya pada C:/sqlite/

Northwind<-DBI::dbConnect(RSQLite::SQLite(), "C:/sqlite/Northwind_large.sqlite")

Dapat dilihat di syntax di atas, kita tidak perlu menggunakan path=, karena C:/sqlite/db/Northwind_large.sqlite langsung didentifikasi langsung sebagai path

class(Northwind)
## [1] "SQLiteConnection"
## attr(,"package")
## [1] "RSQLite"

Perhatikan bahwa syntax di atas tidak membaca data ke dalam R seperti halnya fungsi read_csv() melainkan berupa instruksi kepada R untuk mengkoneksikan database SQLite yang terdapat pada file Northwind_large.sqlite.

Selanjutnya, fungsi dbListTables dapat digunakan untuk melihat tables yang terdapat di dalam database.

RSQLite::dbListTables(Northwind)
##  [1] "Category"             "Customer"             "CustomerCustomerDemo"
##  [4] "CustomerDemographic"  "Employee"             "EmployeeTerritory"   
##  [7] "Order"                "OrderDetail"          "Product"             
## [10] "ProductDetails_V"     "Region"               "Shipper"             
## [13] "Supplier"             "Territory"

Untuk mengakses tabel pada database dapat digunakan fungsi tbl(database, “table”) dari package dplyr. Misalkan, kita ingin melihat isi tabel Product dari database Northwind_large.sqlite.

product<-dplyr::tbl(Northwind,"Product")
class(product)
## [1] "tbl_SQLiteConnection" "tbl_dbi"              "tbl_sql"             
## [4] "tbl_lazy"             "tbl"

Berikut adalah isi dari obyek product

product
## # Source:   table<Product> [?? x 10]
## # Database: sqlite 3.36.0 [C:\sqlite\Northwind_large.sqlite]
##       Id ProductName           SupplierId CategoryId QuantityPerUnit   UnitPrice
##    <int> <chr>                      <int>      <int> <chr>                 <dbl>
##  1     1 Chai                           1          1 10 boxes x 20 ba~      18  
##  2     2 Chang                          1          1 24 - 12 oz bottl~      19  
##  3     3 Aniseed Syrup                  1          2 12 - 550 ml bott~      10  
##  4     4 Chef Anton's Cajun S~          2          2 48 - 6 oz jars         22  
##  5     5 Chef Anton's Gumbo M~          2          2 36 boxes               21.4
##  6     6 Grandma's Boysenberr~          3          2 12 - 8 oz jars         25  
##  7     7 Uncle Bob's Organic ~          3          7 12 - 1 lb pkgs.        30  
##  8     8 Northwoods Cranberry~          3          2 12 - 12 oz jars        40  
##  9     9 Mishi Kobe Niku                4          6 18 - 500 g pkgs.       97  
## 10    10 Ikura                          4          8 12 - 200 ml jars       31  
## # ... with more rows, and 4 more variables: UnitsInStock <int>,
## #   UnitsOnOrder <int>, ReorderLevel <int>, Discontinued <int>

FROM DPLYR to SQL

Seandainya kita ingin mengetahui minimum stok untuk produk dengan harga di atas $20 untuk setiap supplier. Untuk memperoleh informasi tersebut kita dapat menuliskan syntax berikut ini.

q<-product %>%
  filter(UnitPrice>20) %>% 
  group_by(SupplierId) %>% 
  summarize(stock=min(UnitsInStock)) %>%
  arrange(desc(stock))
q
## Warning: Missing values are always removed in SQL.
## Use `MIN(x, na.rm = TRUE)` to silence this warning
## This warning is displayed only once per session.
## # Source:     lazy query [?? x 2]
## # Database:   sqlite 3.36.0 [C:\sqlite\Northwind_large.sqlite]
## # Ordered by: desc(stock)
##    SupplierId stock
##         <int> <int>
##  1         25   115
##  2          9   104
##  3          8    40
##  4          6    35
##  5          4    29
##  6         15    26
##  7          5    22
##  8         26    21
##  9         28    19
## 10         29    17
## # ... with more rows
class(q)
## [1] "tbl_SQLiteConnection" "tbl_dbi"              "tbl_sql"             
## [4] "tbl_lazy"             "tbl"

dplyr mampu menejermahkan pipeline dengan fungsi show_query() seperti contoh di bawah ini

dplyr::show_query(q)
## <SQL>
## SELECT `SupplierId`, MIN(`UnitsInStock`) AS `stock`
## FROM `Product`
## WHERE (`UnitPrice` > 20.0)
## GROUP BY `SupplierId`
## ORDER BY `stock` DESC

Combining Multiple Tables with dplyr in R

Untuk mempelajari mengenai penggabungan tables ini, kita akan menggunakan Datasets Band membership dari package dplyr. Datasets ini terdiri dari 3 buah tibble, dengan ukuran data yang kecil, yaitu hanya 3 baris dan 2 kolom.

data("band_members")
band_members
## # A tibble: 3 x 2
##   name  band   
##   <chr> <chr>  
## 1 Mick  Stones 
## 2 John  Beatles
## 3 Paul  Beatles
data("band_instruments")
band_instruments
## # A tibble: 3 x 2
##   name  plays 
##   <chr> <chr> 
## 1 John  guitar
## 2 Paul  bass  
## 3 Keith guitar
data("band_instruments2")
band_instruments2
## # A tibble: 3 x 2
##   artist plays 
##   <chr>  <chr> 
## 1 John   guitar
## 2 Paul   bass  
## 3 Keith  guitar

Agar diperhatikan, band_instruments dan band_instruments2 memiliki data yang sama, namun berbeda pada penamaan kolom nya, band_instruments menggunakan name, yang sama dengan nama kolom di band_members, sedangkan band_instruments2 menggunakan artist

Fungsi yang akan digunakan dalam penggabungan tables ini berasal dari package dplyr

inner_join() menghasilkan semua baris pada table x yang memiliki kesamaan nilai dengan table y, dan semua kolom dari x dan y. Misal hendak menggabungkan band_members dan band_instruments secara inner_join dapat menggunakan syntax berikut ini :

inner_join(band_members,band_instruments)
## Joining, by = "name"
## # A tibble: 2 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 John  Beatles guitar
## 2 Paul  Beatles bass
band_members %>% inner_join(band_instruments)
## Joining, by = "name"
## # A tibble: 2 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 John  Beatles guitar
## 2 Paul  Beatles bass

left_join() menghasilkan semua baris pada table x, dan semua kolom pada x dan y, dimana untuk baris pada x yang tidak memiliki kesamaan dengan y diisi dengan nilai NApada kolom yang baru. Misalhendak menggabungkan band_members dan band_instruments secara left_join dapat menggunakan syntax berikut ini :

left_join(band_members,band_instruments)
## Joining, by = "name"
## # A tibble: 3 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 Mick  Stones  <NA>  
## 2 John  Beatles guitar
## 3 Paul  Beatles bass

right_join() menghasilkan semua baris pada table y, dan semua kolom pada x dan y, dimana untuk baris pada y yang tidak memiliki kesamaan dengan x akan diisi dengan nilai NA pada kolom yang baru. Misal hendak menggabungkan band_members dan band_instruments secara right_join dapat menggunakan syntax berikut ini :

right_join(band_members,band_instruments)
## Joining, by = "name"
## # A tibble: 3 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 John  Beatles guitar
## 2 Paul  Beatles bass  
## 3 Keith <NA>    guitar

full_join() menghasilkan semua baris dan kolom dari x dan y. Jika ada nilai yang tidak sama (match) antara x dan y, maka akan bernilai NA

full_join(band_members,band_instruments)
## Joining, by = "name"
## # A tibble: 4 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 Mick  Stones  <NA>  
## 2 John  Beatles guitar
## 3 Paul  Beatles bass  
## 4 Keith <NA>    guitar

semi_join() menghasilkan semua baris pada table x yang memiliki kesamaan nilai dengan table y, dan semua kolom dari x. Ini mirip dengan inner_join(), bedanya inner_join() mengembalikan semua kolom dari x dan y.

semi_join(band_members,band_instruments)
## Joining, by = "name"
## # A tibble: 2 x 2
##   name  band   
##   <chr> <chr>  
## 1 John  Beatles
## 2 Paul  Beatles

anti_join() menghasilkan semua baris dari x yang TIDAK memiliki kesamaan dengan y, dan semua kolom yang berasal dari x.

anti_join(band_members,band_instruments)
## Joining, by = "name"
## # A tibble: 1 x 2
##   name  band  
##   <chr> <chr> 
## 1 Mick  Stones

Untuk menggabungkan band_members dan band_instruments2 secara full_join dapat menggunakan syntax dibawah ini:

full_join(band_members, band_instruments2, by = c("name" = "artist"))
## # A tibble: 4 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 Mick  Stones  <NA>  
## 2 John  Beatles guitar
## 3 Paul  Beatles bass  
## 4 Keith <NA>    guitar

MEMBUAT PETA

Dalam pembahasan kali ini akan dilakukan pemetaan jumlah keluarga pra sejahtera di Jawa Tengah pada Tahun 2019. Data yang digunakan merupakan data klasifikasi keluarga yang diperoleh dari BPS

Langkah pertama yang dilakukan yaitu load package

library(sf)
## Warning: package 'sf' was built under R version 4.0.5
## Linking to GEOS 3.9.0, GDAL 3.2.1, PROJ 7.2.1
library(ggplot2)
library(tigris)
## Warning: package 'tigris' was built under R version 4.0.5
## To enable 
## caching of data, set `options(tigris_use_cache = TRUE)` in your R script or .Rprofile.
library(dplyr)

Kemudian memasukkan file SHP. Untuk memasukkan Data SHP, bisa dilakukan dengan melakukan akses pada file SHP yang telah anda download

Admin2Kabupaten<-"C:/Users/DELL/Documents/PASCASARJANA/Sains Data/idn_adm_bps_20200401_shp/idn_admbnda_adm2_bps_20200401.shp"

Untuk mengetahui seperti apa file SHP tersebut di R, bisa memakai fungsi glimpse dari Package dplyr

glimpse(Admin2Kabupaten)
##  chr "C:/Users/DELL/Documents/PASCASARJANA/Sains Data/idn_adm_bps_20200401_shp/idn_admbnda_adm2_bps_20200401.shp"

Selanjutnya merubahnya menjadi melalui fungsi ‘st_read’ dari Package ‘sf’

Admin2<-st_read(Admin2Kabupaten)
## Reading layer `idn_admbnda_adm2_bps_20200401' from data source 
##   `C:\Users\DELL\Documents\PASCASARJANA\Sains Data\idn_adm_bps_20200401_shp\idn_admbnda_adm2_bps_20200401.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 522 features and 14 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 95.01079 ymin: -11.00762 xmax: 141.0194 ymax: 6.07693
## Geodetic CRS:  WGS 84

Untuk melihat hasil yang sudah berubah menggunakan syntax dibawah ini:

glimpse(Admin2)
## Rows: 522
## Columns: 15
## $ Shape_Leng <dbl> 2.360029, 1.963994, 4.590182, 3.287754, 4.448584, 4.907219,~
## $ Shape_Area <dbl> 0.22896809, 0.15413587, 0.23639581, 0.31616114, 0.34303826,~
## $ ADM2_EN    <chr> "Aceh Barat", "Aceh Barat Daya", "Aceh Besar", "Aceh Jaya",~
## $ ADM2_PCODE <chr> "ID1107", "ID1112", "ID1108", "ID1116", "ID1103", "ID1102",~
## $ ADM2_REF   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ ADM2ALT1EN <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ ADM2ALT2EN <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ ADM1_EN    <chr> "Aceh", "Aceh", "Aceh", "Aceh", "Aceh", "Aceh", "Aceh", "Ac~
## $ ADM1_PCODE <chr> "ID11", "ID11", "ID11", "ID11", "ID11", "ID11", "ID11", "ID~
## $ ADM0_EN    <chr> "Indonesia", "Indonesia", "Indonesia", "Indonesia", "Indone~
## $ ADM0_PCODE <chr> "ID", "ID", "ID", "ID", "ID", "ID", "ID", "ID", "ID", "ID",~
## $ date       <date> 2019-12-20, 2019-12-20, 2019-12-20, 2019-12-20, 2019-12-20~
## $ validOn    <date> 2020-04-01, 2020-04-01, 2020-04-01, 2020-04-01, 2020-04-01~
## $ validTo    <date> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ geometry   <MULTIPOLYGON [°]> MULTIPOLYGON (((96.26836 4...., MULTIPOLYGON (~

Memasukkan File Data CSV

Setiap File SHP biasanya disertai bentuk file lainnya, seperti : cpg, dbf, prj,sbn,sbx,shp.xml,shx kita hanya perlu fokus pada file dbf atau dBase database file saja.

Hal yang dapat dilakukan yaitu buka file dbf nya, tambahkan 1 atau lebih kolom baru dengan nama kolom sebagai Data Kuantitatif yang akan menentukan gradasi warna, lalu simpan sebagai csv. File dbf bisa dengan mudah anda buka melalui Microsoft Excel atau software lain yang sejenis.

Jateng<-read.csv("C:/Users/DELL/Documents/PASCASARJANA/Sains Data/datakeluarga.csv",header=TRUE, sep=";")

Merge Data dilakukan dengan memmbandingkan primary key antara Spatial Data (Admin2 hasil import file SHP) dan Data Frame (JabarIndonesia hasil Import File CSV), karena CSV yang dipakai berasal dari file dbf biasanya tidak ada masalah. Ini menggunakan fungsi geo_join() dari package tigris

merged_Jateng <- geo_join(spatial_data=Admin2, 
                                  data_frame=Jateng, by_sp="ADM2_PCODE", 
                                  by_df="ADM2_PCODE", how = "inner")
## Warning: We recommend using the dplyr::*_join() family of functions instead.

Untuk mengatur warna dapat menggunakan syntax di bawah ini

mycol <- c("green", "yellow", "red", "red4")

Menampilkan Peta

pDATA<-ggplot()+
  geom_sf(data=merged_Jateng,aes(fill=DATA))+
  scale_fill_gradientn(colours=mycol)+
  labs(title="Jumlah Keluarga Pra Sejahtera di Jawa Tengah Tahun 2019 (Jawa Tengah dan Indonesia)")
pDATA

CARA LAIN MEMBUAT PETA

Memanggil Data

JatengJawa<-read.csv("C:/Users/DELL/Documents/PASCASARJANA/Sains Data/jatengjawa.csv",header=TRUE, sep=";")

Menggabungkan Data

merged_JatengJawa <- geo_join(spatial_data=Admin2, 
                             data_frame=JatengJawa, by_sp="ADM2_PCODE", 
                             by_df="ADM2_PCODE", how = "inner")
## Warning: We recommend using the dplyr::*_join() family of functions instead.

Menampilkan Plot Data

pDATA2<-ggplot()+
  geom_sf(data=merged_JatengJawa,aes(fill=DATA))+
  scale_fill_gradientn(colours=mycol)+
  labs(title="Jumlah Keluarga Pra Sejahtera di Jawa Tengah Tahun 2019 (Jawa Tengah dan Pulau Jawa)")
pDATA2

Gambar diatas merupakan hasil pemetaan jumlah keluarga pra sejahtera menggunakan peta pulau jawa

CARA KETIGA MEMBUAT PETA

Jateng1<-read.csv("C:/Users/DELL/Documents/PASCASARJANA/Sains Data/jateng.csv",
                    header=TRUE, sep=";")
merged_Jateng1 <- geo_join(spatial_data=Admin2, 
                             data_frame=Jateng1, by_sp="ADM2_PCODE", 
                             by_df="ADM2_PCODE", how = "inner")
## Warning: We recommend using the dplyr::*_join() family of functions instead.
pDATA3<-ggplot()+
  geom_sf(data=merged_Jateng1,aes(fill=DATA))+
  scale_fill_gradientn(colours=mycol)+
  labs(title="Jumlah Keluarga Pra Sejahtera di Jawa Tengah Tahun 2019")
pDATA3

Gambar diatas merupakan hasil pemetaan jumlah keluarga Pra Sejahtera di Jawa Tengah dengan peta Jawa Tengah

Perbedaan Dari Ketiga Peta

Perbedaan yang mendasar adalah dari file yang dimasukkan.

Perbedaan Dimensi Data

dim (Jateng)
## [1] 522  10
dim (JatengJawa)
## [1] 122   5
dim (Jateng1)
## [1] 35  5

Pada output diatas dapat terlihat terdapat perbedaan dimensi pada file yang dimasukkan

Perbedaan lainnya dapat dilihat menggunakan syntax (head) dan (glimpse)

head (Jateng)
##   Shape_Leng Shape_Area       ADM2_EN ADM2_PCODE DATA  X X.1 X.2 X.3 X.4
## 1   6.732280  0.1494304      Simeulue     ID1101   NA NA  NA  NA  NA  NA
## 2   4.907219  0.1534414  Aceh Singkil     ID1102   NA NA  NA  NA  NA  NA
## 3   4.448584  0.3430383  Aceh Selatan     ID1103   NA NA  NA  NA  NA  NA
## 4   3.473021  0.3374562 Aceh Tenggara     ID1104   NA NA  NA  NA  NA  NA
## 5   5.037148  0.4434042    Aceh Timur     ID1105   NA NA  NA  NA  NA  NA
## 6   3.676889  0.3834894   Aceh Tengah     ID1106   NA NA  NA  NA  NA  NA
head(JatengJawa)
##   Shape_Leng  Shape_Area              ADM2_EN ADM2_PCODE DATA
## 1  1.2780153 0.000880270     Kepulauan Seribu     ID3101   NA
## 2  0.8389714 0.011833671 Kota Jakarta Selatan     ID3171   NA
## 3  1.0211135 0.015089248   Kota Jakarta Timur     ID3172   NA
## 4  0.3837589 0.003912531   Kota Jakarta Pusat     ID3173   NA
## 5  0.5903399 0.010251018   Kota Jakarta Barat     ID3174   NA
## 6  1.1430047 0.011458928   Kota Jakarta Utara     ID3175   NA
head (Jateng1)
##   Shape_Leng Shape_Area      ADM2_EN ADM2_PCODE  DATA
## 1   3.546142 0.19212088      Cilacap     ID3301 87447
## 2   2.131290 0.11384822     Banyumas     ID3302 70516
## 3   1.535054 0.06616744  Purbalingga     ID3303 45441
## 4   2.326238 0.09411435 Banjarnegara     ID3304 38936
## 5   1.987110 0.10905342      Kebumen     ID3305 48877
## 6   1.623563 0.08932018    Purworejo     ID3306 42216
glimpse(Jateng)
## Rows: 522
## Columns: 10
## $ Shape_Leng <dbl> 6.7322801, 4.9072187, 4.4485844, 3.4730210, 5.0371477, 3.67~
## $ Shape_Area <dbl> 0.149430413, 0.153441369, 0.343038263, 0.337456209, 0.44340~
## $ ADM2_EN    <chr> "Simeulue", "Aceh Singkil", "Aceh Selatan", "Aceh Tenggara"~
## $ ADM2_PCODE <chr> "ID1101", "ID1102", "ID1103", "ID1104", "ID1105", "ID1106",~
## $ DATA       <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ X          <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ X.1        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ X.2        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ X.3        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
## $ X.4        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
glimpse (JatengJawa)
## Rows: 122
## Columns: 5
## $ Shape_Leng <dbl> 1.2780153, 0.8389714, 1.0211135, 0.3837589, 0.5903399, 1.14~
## $ Shape_Area <dbl> 0.000880270, 0.011833671, 0.015089248, 0.003912531, 0.01025~
## $ ADM2_EN    <chr> "Kepulauan Seribu", "Kota Jakarta Selatan", "Kota Jakarta T~
## $ ADM2_PCODE <chr> "ID3101", "ID3171", "ID3172", "ID3173", "ID3174", "ID3175",~
## $ DATA       <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,~
glimpse(Jateng1)
## Rows: 35
## Columns: 5
## $ Shape_Leng <dbl> 3.546142, 2.131290, 1.535054, 2.326238, 1.987110, 1.623563,~
## $ Shape_Area <dbl> 0.19212088, 0.11384822, 0.06616744, 0.09411435, 0.10905342,~
## $ ADM2_EN    <chr> "Cilacap", "Banyumas", "Purbalingga", "Banjarnegara", "Kebu~
## $ ADM2_PCODE <chr> "ID3301", "ID3302", "ID3303", "ID3304", "ID3305", "ID3306",~
## $ DATA       <int> 87447, 70516, 45441, 38936, 48877, 42216, 47409, 94540, 882~

Reference

Anisa, R., Dito, G.A., Nurussadad, A.A. Database Query With R.

Nurussadad, A.A. Peta Choropleth.