1 Introduction

1.1 Our Purpose

Polusi udara merupakan sebuah isu global yang saat ini ada di dunia, khususnya di kota-kota besar. Itu sebabnya banyak sekali alat yang digunakan untuk menghitung kadar kualitas udara pada beberapa titik di kota-kota tersebut untuk mengetahui bagaimana kualitas udaranya.

Data-data yang diambil merupakan data-data polutan udara yang ditangkap oleh alat khusus dan diubah dalam bentuk data yang nantinya disajikan dan dapat dianalisis.

Pada project ini saya menggunakan data polusi udara di kota Seoul, Korea Selatan. Data tersebut didapatkan dari Kaggle dengan link berikut ini. Air Pollution in Seoul.

Kali ini saya akan membahas langkah-langkah dalam membuat analisis dan visualisasi data dalam bahasa R terhadap data polusi udara yang ada ini. Dari data ini, kita dapat melihat bagaimana kualitas udara di beberapa titik atau wilayah di kota Seoul selama tahun 2017 hingga tahun 2019.

Data ini menyediakan rata-rata nilai dari 6 polutan yaitu : - SO2 - NO2 - CO - O3 - PM10 - PM2.5

1.2 Preparation

Kita panggil setiap library yang dibutuhkan dalam pembuatan data visualisasi ini nantinya.

# data wrangling
library(dplyr)
library(tidyr)

# date-time
library(lubridate)

# visualization
library(ggplot2)

Selain itu, karena data yang kita gunakan nanti terdapat data latitude dan longitude yang merupakan data numeric dengan 15 digit dibelakang koma, maka kita set global option agar datanya tetap penuh.

options(scipen=999)

2 Data Preparation

2.1 Read Data

Kita mulai dengan membaca dataset.

Kita akan memanggil 2 dataset yaitu : 1. Measurement_summary.csv, yang berisi data lengkap tiap titik dan nilai polutan di setiap station / titik pengambilan nilai kualitas udara. Data ini akan kita simpan dalam dataframe summary_pollution. 2. Measurement_station_info.csv, yang berisi data detail dari setiap station / titik pengambilan nilai kualitas udara. Data ini akan kita simpan dalam dataframe station_info.

summary_pollution <- read.csv("Measurement_summary.csv")
station_info <- read.csv("Measurement_station_info.csv")

2.2 Data Inspection

Kemudian kita melakukan inspeksi sampel data dengan menggunakan head atas kedua data tersebut.

head(summary_pollution)
head(station_info)

Disini kita mendapatkan informasi bahwa kita bisa mendapatkan nama station / nama district untuk data summary pada data station_info dimana terdapat 25 data district sesuai jumlah data unique pada kolom Station.code.

length(unique(summary_pollution$Station.code))
## [1] 25

Kemudian, mari kita lihat masing-masing tipe data dari tiap kolom / variabel.

str(summary_pollution)
## 'data.frame':    647511 obs. of  11 variables:
##  $ Measurement.date: chr  "2017-01-01 00:00" "2017-01-01 01:00" "2017-01-01 02:00" "2017-01-01 03:00" ...
##  $ Station.code    : int  101 101 101 101 101 101 101 101 101 101 ...
##  $ Address         : chr  "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" ...
##  $ Latitude        : num  37.6 37.6 37.6 37.6 37.6 ...
##  $ Longitude       : num  127 127 127 127 127 ...
##  $ SO2             : num  0.004 0.004 0.004 0.004 0.003 0.003 0.003 0.003 0.004 0.003 ...
##  $ NO2             : num  0.059 0.058 0.056 0.056 0.051 0.046 0.049 0.045 0.047 0.047 ...
##  $ O3              : num  0.002 0.002 0.002 0.002 0.002 0.002 0.002 0.002 0.002 0.002 ...
##  $ CO              : num  1.2 1.2 1.2 1.2 1.2 1.1 1.1 1 1.1 1.1 ...
##  $ PM10            : num  73 71 70 70 69 70 66 71 72 74 ...
##  $ PM2.5           : num  57 59 59 58 61 61 57 60 60 63 ...

Dari dataframe air_polution, 11 variabel tersebut terbagi menjadi 3 tipe data, yaitu character, integer dan numeric (double).

  • Measurement.date : terbaca sebagai tipe data character. Seharusnya, tipe data ini bisa diubah menjadi tipe data date.
  • Station.code : terbaca sebagai tipe data integer, untuk data kode, seharusnya walaupun datanya berupa angka, akan lebih baik jika tipe datanya adalah factor karena station.code datanya menunjukkan 25 kode district yang ada di Seoul, sehingga lebih cocok jika menggunakan factor.
  • Address : terbaca sebagai character. Sudah sesuai.
  • Lattitude, Longitude : terbaca sebagai numeric / double. Sudah sesuai.
  • Seluruh data polutan (SO2, dsb) : terbaca sebagai numeric / double. Sudah sesuai. Karena berpotensi memiliki nilai pecahan dalam satuannya.

Namun sebelum kita melakukan proses manipulasi tipe data, akan lebih baik jika kita melakukan pengecekan missing value pada data kita.

colSums(is.na(summary_pollution))
## Measurement.date     Station.code          Address         Latitude 
##                0                0                0                0 
##        Longitude              SO2              NO2               O3 
##                0                0                0                0 
##               CO             PM10            PM2.5 
##                0                0                0

Tidak ditemukan data NA pada data air_polution.

2.3 Data Manipulation

Kita lakukan proses perubahan tipe data untuk variabel Measurement.date dan Station.code.

  1. Mengubah Station.code menjadi tipe data factor.
summary_pollution$Station.code <- as.factor(summary_pollution$Station.code)
str(summary_pollution)
## 'data.frame':    647511 obs. of  11 variables:
##  $ Measurement.date: chr  "2017-01-01 00:00" "2017-01-01 01:00" "2017-01-01 02:00" "2017-01-01 03:00" ...
##  $ Station.code    : Factor w/ 25 levels "101","102","103",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Address         : chr  "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" "19, Jong-ro 35ga-gil, Jongno-gu, Seoul, Republic of Korea" ...
##  $ Latitude        : num  37.6 37.6 37.6 37.6 37.6 ...
##  $ Longitude       : num  127 127 127 127 127 ...
##  $ SO2             : num  0.004 0.004 0.004 0.004 0.003 0.003 0.003 0.003 0.004 0.003 ...
##  $ NO2             : num  0.059 0.058 0.056 0.056 0.051 0.046 0.049 0.045 0.047 0.047 ...
##  $ O3              : num  0.002 0.002 0.002 0.002 0.002 0.002 0.002 0.002 0.002 0.002 ...
##  $ CO              : num  1.2 1.2 1.2 1.2 1.2 1.1 1.1 1 1.1 1.1 ...
##  $ PM10            : num  73 71 70 70 69 70 66 71 72 74 ...
##  $ PM2.5           : num  57 59 59 58 61 61 57 60 60 63 ...

Kita sudah mendapatkan Station.code sebagai factor dengan 25 level.

  1. Mengubah Measurement.date menjadi tipe data datetime. Kita harus tahu bahwa format yang digunakan pada data tersebut:
tail(summary_pollution)

Data tanggal yang digunakan adalah : YYYY-MM-DD HH:MM Jadi kita ubah dulu sesuai dengan format tersebut.

summary_pollution$Measurement.date <- ymd_hm(summary_pollution$Measurement.date)
tail(summary_pollution)

Kemudian kita bisa melakukan ekstarasi data datetime dari hasil ekstrasi variabel / kolom Measurement.date tersebut. Kita buat 4 kolom baru dari data tersebut, antara lain :

1. Tahun

summary_pollution$Measurement.Year <- year(summary_pollution$Measurement.date)

2. Month

summary_pollution$Measurement.Month <- month(summary_pollution$Measurement.date, label = T, abbr = T)

3. Day

summary_pollution$Measurement.Day <- wday(summary_pollution$Measurement.date, label = T, abbr = T)

4. Jam

summary_pollution$Measurement.Hour <- hour(summary_pollution$Measurement.date)

Berikut ini summary akhir dari dataframe yang akan kita gunakan untuk visualisasi.

summary(summary_pollution)
##  Measurement.date                  Station.code      Address         
##  Min.   :2017-01-01 00:00:00.00   110    : 25906   Length:647511     
##  1st Qu.:2017-09-27 19:00:00.00   116    : 25906   Class :character  
##  Median :2018-06-24 14:00:00.00   101    : 25905   Mode  :character  
##  Mean   :2018-06-27 21:39:49.24   102    : 25905                     
##  3rd Qu.:2019-03-30 15:30:00.00   106    : 25905                     
##  Max.   :2019-12-31 23:00:00.00   111    : 25905                     
##                                   (Other):492079                     
##     Latitude       Longitude          SO2                 NO2          
##  Min.   :37.45   Min.   :126.8   Min.   :-1.000000   Min.   :-1.00000  
##  1st Qu.:37.52   1st Qu.:126.9   1st Qu.: 0.003000   1st Qu.: 0.01600  
##  Median :37.54   Median :127.0   Median : 0.004000   Median : 0.02500  
##  Mean   :37.55   Mean   :127.0   Mean   :-0.001795   Mean   : 0.02252  
##  3rd Qu.:37.58   3rd Qu.:127.0   3rd Qu.: 0.005000   3rd Qu.: 0.03800  
##  Max.   :37.66   Max.   :127.1   Max.   : 3.736000   Max.   :38.44500  
##                                                                        
##        O3                 CO               PM10             PM2.5        
##  Min.   :-1.00000   Min.   :-1.0000   Min.   :  -1.00   Min.   :  -1.00  
##  1st Qu.: 0.00800   1st Qu.: 0.3000   1st Qu.:  22.00   1st Qu.:  11.00  
##  Median : 0.02100   Median : 0.5000   Median :  35.00   Median :  19.00  
##  Mean   : 0.01798   Mean   : 0.5092   Mean   :  43.71   Mean   :  25.41  
##  3rd Qu.: 0.03400   3rd Qu.: 0.6000   3rd Qu.:  53.00   3rd Qu.:  31.00  
##  Max.   :33.60000   Max.   :71.7000   Max.   :3586.00   Max.   :6256.00  
##                                                                          
##  Measurement.Year Measurement.Month Measurement.Day Measurement.Hour
##  Min.   :2017     Oct    : 55800    Sun:92100       Min.   : 0.0    
##  1st Qu.:2017     Jan    : 55775    Mon:93233       1st Qu.: 6.0    
##  Median :2018     Aug    : 55603    Tue:93350       Median :12.0    
##  Mean   :2018     Dec    : 55500    Wed:92140       Mean   :11.5    
##  3rd Qu.:2019     Jul    : 55275    Thu:92346       3rd Qu.:17.0    
##  Max.   :2019     May    : 54625    Fri:92742       Max.   :23.0    
##                   (Other):314933    Sat:91600

2.4 Exploratory Data Analysis

Kita lihat persebaran data kita dengan histogram berdasarkan tahun.

hist(summary_pollution$Measurement.Year)

Data kita jumlahnya sama semua tiap tahunnya.

plot(summary_pollution$Measurement.Day)

Data juga tersebar secara merata secara harian.

plot(summary_pollution$Station.code)

Data juga tersebar secara merata pada setiap station.

2.5 Explanatory Data Analysis

Kita mulai melakukan proses visualisasi dengan menggunakan data polutan dan juga dengan timeframe waktu. Misalnya kita ambil salah satu polutan 03 (Ozone) dan kita masukkan dalam plot dengan sumbu waktu yaitu tahun.

pollution_03 <- aggregate(O3 ~ Measurement.Year + Measurement.Hour,
                             data = summary_pollution,
                             FUN = mean)

pollution_03
ggplot(data = pollution_03, 
       mapping = aes(x = Measurement.Hour,
                     y = O3))+
  geom_line()

# visualisasi geom_line dengan group
# kanvas
ggplot(data = pollution_03, 
       mapping = aes(x = Measurement.Hour,
                     y = O3))+
  
  # layer 1: line plot 
  geom_line(mapping = aes(group = Measurement.Year))

Memberikan warna dan ketebalan garis.

# visualisasi geom_line dengan color
# kanvas
ggplot(data = pollution_03, 
       mapping = aes(x = Measurement.Hour,
                     y = O3,
                     
                     # mewarnai line
                     color = Measurement.Year))+
  
  # layer 1: line plot 
  geom_line(mapping = aes(group = Measurement.Year),
            
            # menebalkan garis line
            size = 0.75 )

Menambahkan titik.

# visualisasi geom_line dengan geom_point
# kanvas
ggplot(data = pollution_03, 
       mapping = aes(x = Measurement.Hour,
                     y = O3,
                     
                     # mewarnai line
                     color = Measurement.Year))+
  
  # layer 1: line plot 
  geom_line(mapping = aes(group = Measurement.Year),
            
            # menebalkan garis line
            size = 0.5 )+
  
  # layer 2: menambahkan titik
  geom_point(size = 1.5)

2.6 Conclusion

Jadi, berdasarkan data polutan O3 (Ozone) dalam rentang waktu 1 hari pada tiap jam selama 3 tahun (pada tahun 2017 s.d 2019), nilai O3 lebih rendah pada pagi hari, meningkat setelah pukul 7 hingga pukul 15 (pada puncaknya) dan kembali turun hinggak akhir hari. Trend tersebut rata-rata sama tiap tahunnya.

Selama 3 tahun, tahun 2019 adalah tahun dengan nilai polutan Ozone (O3 terendah) selama 3 tahun.