P3a-Database Queries with R
Database Queries
Beberapa package yang digunakan untuk bekerja dengan database menggunakan R software adalah:
DBI
berfungsi memisahkan konektivitas ke DBMS menjadi “front-end” dan “back-end”. Aplikasi hanya menggunakan API front-end yang terbuka. Fasilitas back-end yang berkomunikasi dengan DBMS tertentu (SQLite, MySQL, PostgreSQL, MonetDB, dll.) disediakan oleh driver (package lain) yang dipanggil secara otomatis.dplyr
dandbplyr
memiliki SQL back-end yang digeneralisasi untuk bisa bekerja dengan database.odbc
menyediakan antarmuka yang sesuai dengan DBI untuk driver Open Database Connectivity (ODBC). Hal ini memungkinkan koneksi yang efisien dan mudah diatur ke database apa pun dengan driver ODBC yang tersedia, termasuk SQL Server, Oracle, MySQL, PostgreSQL, SQLite, dan lainnya.
Connection to a Database
Kali ini contoh pemanggilan database akan menggunakan contoh data Northwind
. Untuk dapat melakukannya, package DBI
dan RSQLite
perlu di-install terlebih dulu.
install.packages(c("RSQLite", "DBI"), dependencies = TRUE)
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)
## -- Attaching packages --------------------------------------- tidyverse 1.3.0 --
## v ggplot2 3.3.3 v purrr 0.3.4
## v tibble 3.0.6 v dplyr 1.0.4
## v tidyr 1.1.2 v stringr 1.4.0
## v readr 1.4.0 v forcats 0.5.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(RSQLite)
library(DBI)
Secara umum, koneksi terhadap database pada R software adalah dengan menggunakan syntax berikut:
DBI::dbConnect(RSQLite::SQLite(), path = ":dbname:")
Fungsi dapat pula dijalankankan tanpa memanggil package dengan perintah library()
atau require()
, jika syntax yang ditulis menyertakan nama package tempat fungsi tersebut berasal. Penyertaan ini dengan menggunakan tanda ::
.
Untuk menjalankan syntax berikut ini, Anda perlu mengunduh Database Northwind_large.sqlite
dan menyimpannya pada C:/sqlite/db/
<-DBI::dbConnect(RSQLite::SQLite(), "C:/sqlite/db/Northwind_large.sqlite") Northwind
Dapat dilihat di syntax di atas, Anda tidak perlu menggunakan path=
, karena C:/sqlite/db/Northwind_large.sqlite
langsung didentifikasi langsung sebagai path
. Anda akan mempelajari hal seperti ini di Mata Kuliah STA561 - Pemrograman Statistika khususnya di Pertemuan 6 - Pemrograman Fungsi R
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.
::dbListTables(Northwind) RSQLite
## [1] "Category" "Customer" "CustomerCustomerDemo"
## [4] "CustomerDemographic" "Employee" "EmployeeTerritory"
## [7] "Order" "OrderDetail" "Product"
## [10] "ProductDetails_V" "Region" "Shipper"
## [13] "Supplier" "Territory"
Anda bisa melakukan hal yang sama hanya menggunakan syntax dbListTables(Northwind)
, karena di atas Kita telah memanggil package RSQLite
dengan syntax library(RSQLite)
.
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
. Perlu diperhatikan, Kita sudah memasukkan Northwind_large.sqlite
sebagai objek Northwind
<-dplyr::tbl(Northwind,"Product")
productclass(product)
## [1] "tbl_SQLiteConnection" "tbl_dbi" "tbl_sql"
## [4] "tbl_lazy" "tbl"
Perhatikan bahwa product
merupakan object dengan class tbl
yang dapat diperlakukan mirip seperti data.frame
.
Berikut adalah isi dari obyek product
product
## # Source: table<Product> [?? x 10]
## # Database: sqlite 3.34.1 [C:\sqlite\db\Northwind_large.sqlite]
## Id ProductName SupplierId CategoryId QuantityPerUnit UnitPrice
## <int> <chr> <int> <int> <chr> <dbl>
## 1 1 Chai 1 1 10 boxes x 20 ~ 18
## 2 2 Chang 1 1 24 - 12 oz bot~ 19
## 3 3 Aniseed Sy~ 1 2 12 - 550 ml bo~ 10
## 4 4 Chef Anton~ 2 2 48 - 6 oz jars 22
## 5 5 Chef Anton~ 2 2 36 boxes 21.4
## 6 6 Grandma's ~ 3 2 12 - 8 oz jars 25
## 7 7 Uncle Bob'~ 3 7 12 - 1 lb pkgs. 30
## 8 8 Northwoods~ 3 2 12 - 12 oz jars 40
## 9 9 Mishi Kobe~ 4 6 18 - 500 g pkg~ 97
## 10 10 Ikura 4 8 12 - 200 ml ja~ 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.
<-product %>%
qfilter(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.34.1 [C:\sqlite\db\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"
Pada beberapa kasus, data yang digunakan bisa saja berukuran sangat besar sehingga lebih efisien jika disimpan dalam bentuk database. Syntax di atas merupakan contoh cara kita memproses data dalam bentuk database dengan cara menggunakan package dplyr
untuk menghubungkan syntax
pada R
dengan data
pada SQLite
.
dplyr
mampu menejermahkan pipeline dengan fungsi show_query()
seperti contoh di bawah ini.
::show_query(q) dplyr
## <SQL>
## SELECT `SupplierId`, MIN(`UnitsInStock`) AS `stock`
## FROM `Product`
## WHERE (`UnitPrice` > 20.0)
## GROUP BY `SupplierId`
## ORDER BY `stock` DESC
Sebaliknya, kita dapat menuliskan fungsi sql dengan fungsi tbl
dari package dplyr
.
tbl(Northwind, sql("SELECT productname, categoryid, unitprice FROM Product ORDER BY productname LIMIT 10"))
## # Source: SQL [?? x 3]
## # Database: sqlite 3.34.1 [C:\sqlite\db\Northwind_large.sqlite]
## productname categoryid unitprice
## <chr> <int> <dbl>
## 1 Alice Mutton 6 39
## 2 Aniseed Syrup 2 10
## 3 Boston Crab Meat 8 18.4
## 4 Camembert Pierrot 4 34
## 5 Carnarvon Tigers 8 62.5
## 6 Chai 1 18
## 7 Chang 1 19
## 8 Chartreuse verte 1 18
## 9 Chef Anton's Cajun Seasoning 2 22
## 10 Chef Anton's Gumbo Mix 2 21.4
Contoh lainnya, misalkan kita ingin melihat 10 perusahaan pertama dari table Customer
.
tbl(Northwind,"Customer") %>%
select(CompanyName) %>%
head(n=10)
## # Source: lazy query [?? x 1]
## # Database: sqlite 3.34.1 [C:\sqlite\db\Northwind_large.sqlite]
## CompanyName
## <chr>
## 1 Alfreds Futterkiste
## 2 Ana Trujillo Emparedados y helados
## 3 Antonio Moreno Taquería
## 4 Around the Horn
## 5 Berglunds snabbköp
## 6 Blauer See Delikatessen
## 7 Blondesddsl père et fils
## 8 Bólido Comidas preparadas
## 9 Bon app
## 10 Bottom-Dollar Markets
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()
inner_join()
menghasilkan semua baris pada table x yang memiliki kesamaan nilai dengan table y, dan semua kolom dari x dan y.
Misal, Anda hendak menggabungkan band_members
dan band_instruments
secara inner_join
, maka Anda bisa 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
%>% inner_join(band_instruments) band_members
## Joining, by = "name"
## # A tibble: 2 x 3
## name band plays
## <chr> <chr> <chr>
## 1 John Beatles guitar
## 2 Paul Beatles bass
left_join()
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.
Misal, Anda hendak menggabungkan band_members
dan band_instruments
secara left_join
, maka Anda bisa 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()
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, Anda hendak menggabungkan band_members
dan band_instruments
secara right
_join`, maka Anda bisa 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()
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.
Misal, Anda hendak menggabungkan band_members
dan band_instruments
secara full_join
, maka Anda bisa menggunakan syntax berikut ini :
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()
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.
Misal, Anda hendak menggabungkan band_members
dan band_instruments
secara semi_join
, maka Anda bisa menggunakan syntax berikut ini :
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()
anti_join()
menghasilkan semua baris dari x yang TIDAK memiliki kesamaan dengan y, dan semua kolom yang berasal dari x.
Misal, Anda hendak menggabungkan band_members
dan band_instruments
secara anti_join
, maka Anda bisa menggunakan syntax berikut ini :
anti_join(band_members,band_instruments)
## Joining, by = "name"
## # A tibble: 1 x 2
## name band
## <chr> <chr>
## 1 Mick Stones
Catatan
Ada kalanya Anda perlu menggabungkan data seperti band_members
dan band_instruments2
dimana tidak ada nama kolom yang sama, namun sebenarnya bisa digabungkan. Maka Anda memerlukan sedikit tambahan syntax.
Misal,Anda hendak menggabungkan band_members
dan band_instruments2
secara full_join
, maka Anda bisa menggunakan syntax berikut 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
Selengkapnya dapat dipelajari di sini
Referensi
Contributors Data Carpenters. (2020, August 12). SQL databases and R. Data Carpentry. Retrieved from https://datacarpentry.org/R-ecology-lesson/05-r-and-databases.html#Introduction
Wickham, H., & Ruiz, E. (n.d.). Introduction to dbplyr. dbplyr. Retrieved from https://dbplyr.tidyverse.org/
IPB University, rahmaanisa@apps.ipb.ac.id↩︎
IPB University, gerry_dito@apps.ipb.ac.id↩︎
Badan Informasi Geospasial, abdul.aziz@big.go.id↩︎