Ringkasan

Artikel ini menyajikan beberapa visualisasi data kualitas udara di suatu kota di Italy selama setahun. Data diperoleh dari UCI Machine Learning Repository dengan nama data set Air Quality Data Set, kemudian data disiapkan dengan beberapa tahapan hingga data siap disajikan dan ditampilkan dalam bentuk grafik yang menarik. Beberapa grafik menggunakan teknik animasi seperti pada grafik trend suhu dan kelembaban udara untuk lebih menggambarkan perubahannya dari waktu ke waktu. Untuk parameter yang lain disajikan dalam grafik statis. Spesifikasi versi R dan library yang digunakan dapat di lihat pada bagian Sumber Data.

Dari visualisasi data dan analisis regresi yang telah dilakukan, terlihat bahwa suhu udara minimum pada -1.90oC dan maksimum pada 44,6oC. Kadar CO dan NO2 terendah pada pukul 3-5 dini hari dimana aktifitas manusia sangat rendah dalam menggunakan kendaraan bermotor, kemudian kadar CO dan NO2 beranjak naik seiring dengan aktifitas manusia.

1. Polusi Udara

Polusi udara di luar ruangan adalah masalah kesehatan lingkungan utama yang mempengaruhi semua orang di negara berpenghasilan rendah, menengah, dan tinggi.

WHO memperkirakan bahwa pada tahun 2016, sekitar 58% kematian dini terkait polusi udara luar ruangan disebabkan oleh penyakit jantung iskemik dan stroke, sementara 18% kematian masing-masing disebabkan oleh penyakit paru obstruktif kronik dan infeksi saluran pernapasan bawah akut, dan 6% kematian. disebabkan oleh kanker paru-paru.

Beberapa kematian dapat dikaitkan dengan lebih dari satu faktor risiko pada saat yang bersamaan. Misalnya, merokok dan polusi udara sekitar memengaruhi kanker paru-paru. Beberapa kematian akibat kanker paru-paru dapat dicegah dengan meningkatkan kualitas udara ambien, atau dengan mengurangi merokok.

Beberapa parameter pencemaran udara menurut WHO adalah sebagai berikut:

  1. Materi partikulat (PM)
  2. Ozon (O3)
  3. Nitrogen dioksida (NO2)
  4. Sulfur dioksida (SO2).

2. Sumber Data

Data diperoleh dari UCI Machine Learning Repository dengan nama data set Air Quality Data Set. Data kemudian di analisis dengan menggunakan software R versi 4.0.5 dengan beberapa package yang digunakan seperti pada point 3 di bawah ini.

3. Persiapan Data

3.1. Import Package dan Data

Library yang digunakan untuk analisis dan visualisasi data adalah sebagai berikut:

# Import Library

library(tidyverse)  # untuk data wrangling dan plotting
library(lubridate)  # untuk pengaturan tipe data date and time
library(naniar)     # untuk visualisasi missing value
library(gganimate)  # untuk memebuat plot animasi
library(gifski)     # untuk menyimpan plot berekstensi gif
library(ggpmisc)    # untuk memasukkan formula regresi kedalam plot

Versi package yang digunakan adalah sebagai berikut:

  1. Package: tidyverse, version: 1.3.0
  2. Package: lubridate, version: 1.7.10
  3. Package: naniar, version: 0.6.0
  4. Package: gganimate, version: 1.0.7
  5. Package: gifski, version: 1.4.3
  6. Package: ggpmisc, version: 0.3.9

Untuk mengetahui deskripsi package dan versinya, kita dapat menggunakan syntax berikut packageDescription("nama package")

Import data set dengan menggunakan library readr dari library tidyverse

# Import Data

udara <- read_csv("data/AirQualityUCI.csv")
udara

Berikut ini adalah informasi data pada masing-masing kolom yang dirujuk dari website UCI:

  1. Date (DD/MM/YYYY)
  2. Time (HH.MM.SS)
  3. True hourly averaged concentration CO in mg/m3 (reference analyzer)
  4. PT08.S1 (tin oxide) hourly averaged sensor response (nominally CO targeted)
  5. True hourly averaged overall Non Metanic HydroCarbons concentration in microg/m3 (reference analyzer)
  6. True hourly averaged Benzene concentration in microg/m3 (reference analyzer)
  7. PT08.S2 (titania) hourly averaged sensor response (nominally NMHC targeted)
  8. True hourly averaged NOx concentration in ppb (reference analyzer)
  9. PT08.S3 (tungsten oxide) hourly averaged sensor response (nominally NOx targeted)
  10. True hourly averaged NO2 concentration in microg/m3 (reference analyzer)
  11. PT08.S4 (tungsten oxide) hourly averaged sensor response (nominally NO2 targeted)
  12. PT08.S5 (indium oxide) hourly averaged sensor response (nominally O3 targeted)
  13. Temperature in °C
  14. Relative Humidity (%)
  15. AH Absolute Humidity

3.2. Data Cleaning dan Wrangling

Pada tahap ini kita perlu memeriksa struktur data, dimensi data, tipe data, missing value, dan menyiapkan data-data yang kita perlukan, hal ini penting karena agar dapat di analisis dan divisualisasikan.

# Melihat tipe data pada masing-masing kolom dan dimensi datanya

str(udara)
## spec_tbl_df[,15] [9,357 x 15] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ Date         : chr [1:9357] "3/10/2004" "3/10/2004" "3/10/2004" "3/10/2004" ...
##  $ Time         : 'hms' num [1:9357] 18:00:00 19:00:00 20:00:00 21:00:00 ...
##   ..- attr(*, "units")= chr "secs"
##  $ CO(GT)       : num [1:9357] 2.6 2 2.2 2.2 1.6 1.2 1.2 1 0.9 0.6 ...
##  $ PT08.S1(CO)  : num [1:9357] 1360 1292 1402 1376 1272 ...
##  $ NMHC(GT)     : num [1:9357] 150 112 88 80 51 38 31 31 24 19 ...
##  $ C6H6(GT)     : num [1:9357] 11.9 9.4 9 9.2 6.5 4.7 3.6 3.3 2.3 1.7 ...
##  $ PT08.S2(NMHC): num [1:9357] 1046 955 939 948 836 ...
##  $ NOx(GT)      : num [1:9357] 166 103 131 172 131 89 62 62 45 -200 ...
##  $ PT08.S3(NOx) : num [1:9357] 1056 1174 1140 1092 1205 ...
##  $ NO2(GT)      : num [1:9357] 113 92 114 122 116 96 77 76 60 -200 ...
##  $ PT08.S4(NO2) : num [1:9357] 1692 1559 1555 1584 1490 ...
##  $ PT08.S5(O3)  : num [1:9357] 1268 972 1074 1203 1110 ...
##  $ TEMP         : num [1:9357] 13.6 13.3 11.9 11 11.2 11.2 11.3 10.7 10.7 10.3 ...
##  $ RH           : num [1:9357] 48.9 47.7 54 60 59.6 59.2 56.8 60 59.7 60.2 ...
##  $ AH           : num [1:9357] 0.758 0.726 0.75 0.787 0.789 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   Date = col_character(),
##   ..   Time = col_time(format = ""),
##   ..   `CO(GT)` = col_double(),
##   ..   `PT08.S1(CO)` = col_double(),
##   ..   `NMHC(GT)` = col_double(),
##   ..   `C6H6(GT)` = col_double(),
##   ..   `PT08.S2(NMHC)` = col_double(),
##   ..   `NOx(GT)` = col_double(),
##   ..   `PT08.S3(NOx)` = col_double(),
##   ..   `NO2(GT)` = col_double(),
##   ..   `PT08.S4(NO2)` = col_double(),
##   ..   `PT08.S5(O3)` = col_double(),
##   ..   TEMP = col_double(),
##   ..   RH = col_double(),
##   ..   AH = col_double()
##   .. )

Semua kolom tipe datanya telah sesuai kecuali kolom Date, oleh karena itu tipe data pada kolom Date perlu di ganti menjadi tipe Date dengan format yyyy-mm-dd.

# Mengganti tipe data pada kolom Date menjadi tipe data Date

udara$Date <- mdy(udara$Date)
head(udara)

Kemudian kita perlu melihat ada/tidak adanya missing value.

# Melihat missing value pada masing-masing kolom dengan library base

colSums(is.na(udara))
##          Date          Time        CO(GT)   PT08.S1(CO)      NMHC(GT) 
##             0             0             0             0             0 
##      C6H6(GT) PT08.S2(NMHC)       NOx(GT)  PT08.S3(NOx)       NO2(GT) 
##             0             0             0             0             0 
##  PT08.S4(NO2)   PT08.S5(O3)          TEMP            RH            AH 
##             0             0             0             0             0

Untuk lebih mudah dalam melihat adanya missing value pada suatu data frame, maka kita dapat menggunakan library naniar, kemudian hanya dengan satu code, maka dapat dilihat posisi missing value suatu data frame.

# Melihat ada/tidak ada missing value pada data frame

vis_miss(udara)

Tidak terdapat missing value pada data, kemudian kita perlu melihat statistik dari data kita.

# Melihat statistik dari data

summary(udara)
##       Date                Time              CO(GT)         PT08.S1(CO)  
##  Min.   :2004-03-10   Length:9357       Min.   :-200.00   Min.   :-200  
##  1st Qu.:2004-06-16   Class1:hms        1st Qu.:   0.60   1st Qu.: 921  
##  Median :2004-09-21   Class2:difftime   Median :   1.50   Median :1053  
##  Mean   :2004-09-21   Mode  :numeric    Mean   : -34.21   Mean   :1049  
##  3rd Qu.:2004-12-28                     3rd Qu.:   2.60   3rd Qu.:1221  
##  Max.   :2005-04-04                     Max.   :  11.90   Max.   :2040  
##     NMHC(GT)         C6H6(GT)        PT08.S2(NMHC)       NOx(GT)      
##  Min.   :-200.0   Min.   :-200.000   Min.   :-200.0   Min.   :-200.0  
##  1st Qu.:-200.0   1st Qu.:   4.000   1st Qu.: 711.0   1st Qu.:  50.0  
##  Median :-200.0   Median :   7.900   Median : 895.0   Median : 141.0  
##  Mean   :-159.1   Mean   :   1.866   Mean   : 894.6   Mean   : 168.6  
##  3rd Qu.:-200.0   3rd Qu.:  13.600   3rd Qu.:1105.0   3rd Qu.: 284.0  
##  Max.   :1189.0   Max.   :  63.700   Max.   :2214.0   Max.   :1479.0  
##   PT08.S3(NOx)     NO2(GT)         PT08.S4(NO2)   PT08.S5(O3)    
##  Min.   :-200   Min.   :-200.00   Min.   :-200   Min.   :-200.0  
##  1st Qu.: 637   1st Qu.:  53.00   1st Qu.:1185   1st Qu.: 700.0  
##  Median : 794   Median :  96.00   Median :1446   Median : 942.0  
##  Mean   : 795   Mean   :  58.15   Mean   :1391   Mean   : 975.1  
##  3rd Qu.: 960   3rd Qu.: 133.00   3rd Qu.:1662   3rd Qu.:1255.0  
##  Max.   :2683   Max.   : 340.00   Max.   :2775   Max.   :2523.0  
##       TEMP                RH                AH           
##  Min.   :-200.000   Min.   :-200.00   Min.   :-200.0000  
##  1st Qu.:  10.900   1st Qu.:  34.10   1st Qu.:   0.6923  
##  Median :  17.200   Median :  48.60   Median :   0.9768  
##  Mean   :   9.778   Mean   :  39.49   Mean   :  -6.8376  
##  3rd Qu.:  24.100   3rd Qu.:  61.90   3rd Qu.:   1.2962  
##  Max.   :  44.600   Max.   :  88.70   Max.   :   2.2310

Terlihat adanya data yang anomali yang tidak wajar pada kolom TEMP, RH, AH dan kolom-kolom lainnya dengan nilai Min = -200, oleh karena itu data tersebut perlu dieliminir, untuk itu kita dapat menggunakan fungsi filter() pada library dplyr.

Data anomali yang tidak wajar ini perlu di buang karena kita tidak memiliki rujukan untuk merevisi datanya, sehingga lebih baik jika dibuang.

Kemudian untuk analisis data dan visualisasi data, dalam artikel ini hanya akan menggunakan beberapa data saja yaitu data dari kolom/variable Date, Time, CO(GT), NO2(GT), TEMP dan RH

Karena terdapat nama kolom yang mengandung tanda kurung "()", sehingga agar tidak terjadi kesalahan pada script, sebab tanda "()" merupakan fungsi, maka kita perlu mengganti nama kolom yang mengandung tanda tersebut.

# Mengganti nama kolom CO(GT) dan NO2(GT)

names(udara)[3] <- "CO"
names(udara)[10] <- "NO2"

Kemudian kita ambil hanya kolom-kolom yang kita perlukan untuk digunakan pada visualisasi data dengan mengeliminir nilai -200 terlebih dahulu.

# Data Cleaning dan Wrangling

udara <- udara %>%
  filter(CO != -200,
         NO2 != -200,
         TEMP != -200,
         RH != -200) %>%
  select(c(1,2,3,10,13,14))
udara

Sekarang data telah siap digunakan untuk visualisasi dan analisis lebih lanjut.

4. Visualisasi Data

Dalam visualisasi data, terlebih dahulu kita perlu menentukan tujuan untuk mendapat insight dari data kita, berikut adalah beberapa tujuan yang dapat kita gunakan untuk menghasilkan visualisasi data yang tepat.

4.1 Tujuan Visualisasi Data

Berikut adalah beberapa tujuan untuk visualisasi data Air Quality:

  1. Melihat trend suhu udara selama setahun, menggunakan animated line plot.
  2. Melihat trend kelembaban udara selama setahun, menggunakan animated line plot.
  3. Melihat hubungan antara suhu udara dan kelembaban udara, menggunakan scatter plot dan model regresi.
  4. Melihat Sebaran kadar CO dan NO2 pada tiap jam, menggunakan boxplot.
  5. Melihat trend kadar CO dan NO2 selama setahun, menggunakan animate line plot.

Grafik garis dengan animasi digunakan untuk memvisualisasikan time series data dalam bentuk yang lebih menarik dan historical, kita dapat merender grafik menjadi animasi dengan menggunakan library gganimate.

Berikut adalah visualisasi dari masing-masing tujuan di atas beserta insightnya.

4.1.1 Trend Suhu Udara Selama Setahun

# Menyediakan variabel untuk label Suhu dengan satuan derajat selsius.
ylab_suhu <- expression("Suhu ("*~degree*C*")")

# Membuat plot statis.
g_suhu <- ggplot(data = udara, aes(x = Date, y = TEMP)) +
          geom_line(col = "red") +
          geom_point(col= "orange", pch=19, alpha=0.5, size = 0.8) +
          scale_x_date(breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")), 
                                                     to = max(as.Date("2005-04-04")), 
                                                     by = "30 days"),
                       minor_breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")), 
                                                           to = max(as.Date("2005-04-04")), 
                                                           by = "15 days"),
                       date_labels = "%y/%m/%d") +
          scale_y_continuous(limits=c(-5, 45), breaks=seq(-5,45,5), expand = c(0,0)) +
          labs(title = "Trend Suhu Udara Selama Setahun di Italy",
               x = "Bulan/Tahun (yy/mm/dd)", y = ylab_suhu, caption = "Teguh Prasetyo") +
          theme(legend.position = "none") +
          theme(plot.title=element_text(hjust=0.5)) + 
          theme(axis.line=element_line(color="black")) +
          theme(axis.text.x = element_text(angle=45, vjust=0.6)) +
          theme(plot.caption = element_text(color = "blue", face = "italic", size = 8, hjust = 1))

# Pemberian Label untuk Plot Animasi
g_suhulabel <- g_suhu + theme(legend.position = "none") +
    geom_label(aes(x = Date, y=TEMP, label="Suhu"), nudge_x = 10, size=4, hjust=0)
        
        
# Membuat Animated Line Plot
animate(g_suhulabel + transition_reveal(Date), nframes = 100, fps= 4, 
    height = 12, width = 30, units = "cm", res = 150,
    renderer = gifski_renderer(loop = FALSE))

# Statistik Suhu Udara

summary(udara$TEMP)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   -1.90   11.20   16.80   17.76   23.70   44.60

Dari grafik di atas dan summary statistik terlihat bahwa terdapat fluktuasi suhu udara dari suhu minimum pada -1.90oC dan maksimum pada 44,6oC. Kemudian trend suhu udara > 25oC pada bulan Mei hingga Oktober, sedangkan trend suhu udara < 25oC pada bulan Oktober hingg Maret dengan titik terendah pada awal Maret.

4.1.2 Trend Kelembaban Udara Selama Setahun

# Membuat plot statis.
g_rh <- ggplot(data = udara, aes(x = Date, y = RH)) +
          geom_line(col = "blue") +
          geom_point(col= "blue", pch=19, alpha=0.5, size = 0.8) +
          scale_x_date(breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")), 
                                                     to = max(as.Date("2005-04-04")), 
                                                     by = "30 days"),
                       minor_breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")), 
                                                           to = max(as.Date("2005-04-04")), 
                                                           by = "15 days"),
                       date_labels = "%Y/%m/%d") +
          scale_y_continuous(limits=c(0, 100), breaks=seq(0,100,5), expand = c(0,0)) +
          labs(title = "Trend Kelembaban Udara Selama Setahun di Italy",
               x = "Bulan/Tahun (yy/mm/dd)", y = "Kelembaban (%)", caption = "Teguh Prasetyo") +
          theme(legend.position = "none") +
          theme(plot.title=element_text(hjust=0.5)) +
          theme(axis.line=element_line(color="black")) +
          theme(axis.text.x = element_text(angle=45, vjust=0.6)) +
          theme(plot.caption = element_text(color = "blue", face = "italic", size = 8, hjust = 1))

# Pemberian Label untuk Plot Animasi
g_rhlabel <- g_rh + theme(legend.position = "none") +
    geom_label(aes(x = Date, y=RH, label="Kelembaban"), nudge_x = 10, size=4, hjust=0)
        
        
# Membuat Animated Line Plot
animate(g_rhlabel + transition_reveal(Date), nframes = 100, fps= 4, 
    height = 12, width = 30, units = "cm", res = 150,
    renderer = gifski_renderer(loop = FALSE))

Jika dilihat trend kelembaban udara, maka trendnya kebalikan dari trend suhu udara, dimana ketika suhu udara > 25oC, maka kelembaban udara < 50%, begitu juga sebaliknya. Oleh karena itu perlu dianalisis lebih lanjut hubungan antara suhu udara dan kelembaban udara untuk mendapatkan keeratan hubungan antara kedua parameter ini.

4.1.3 Hubungan Antara Suhu Udara dan Kelembaban Udara

Secara sederhana kita dapat menganalisa hubungan dan pola hubungan suhu udara dan kelembaban udara dengan menggunakan analisis korelasi dan regresi sebagai berikut.

#Analisa Simple Linear Regression & Correlation Pearson

suhu_rh <- lm(TEMP ~ RH, data = udara)
  summary(suhu_rh)
## 
## Call:
## lm(formula = TEMP ~ RH, data = udara)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -23.2434  -4.4311   0.5992   5.5921  16.4642 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 31.74068    0.26104  121.59   <2e-16 ***
## RH          -0.28610    0.00503  -56.88   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.305 on 6939 degrees of freedom
## Multiple R-squared:  0.318,  Adjusted R-squared:  0.3179 
## F-statistic:  3235 on 1 and 6939 DF,  p-value: < 2.2e-16

Diketahui bahwa hubungan antara suhu udara dan kelembaban udara sangat nyata secara linear dengan Adjusted R2 = 0.32, dimana hubungan antara suhu udara dan kelembaban udara tergolong tidak erat.

Kemudian untuk lebih tergambar hubungannya, kita dapat membuat diagram pencar (scatter plot) dan memasukkan garis regresi serta formulanya.

# Membuat Regression Plot

# Menyiapkan label X axis dengan simbol 
xlabsuhu_rh <- expression("Suhu ("*~degree*C*")")

# Membuat formula regresi
formulasuhu_rh <- udara$TEMP ~ udara$RH  

g_suhurh <- ggplot(data = udara, aes(x=TEMP, y=RH)) + 
  geom_point(fill= "orange", stroke = 0.5, alpha = 0.5, size = 2.5, pch=21) +
  geom_smooth(method = lm, se=FALSE, size = 1.25, color="blue") +
  stat_poly_eq(aes(label = paste(..eq.label.., sep = "~~~")), 
              label.x = 0.9, label.y = 0.9,
               eq.with.lhs = "italic(hat(y))~`=`~",
               eq.x.rhs = "~italic(x)",
               formula = formulasuhu_rh, parse = TRUE, size = 3.5) +
  stat_poly_eq(aes(label = paste(..rr.label.., sep = "~~~")), 
               label.x = 0.9, label.y = 0.8,
               formula = formulasuhu_rh, parse = TRUE, size = 3.5) +
  scale_x_continuous(limits=c(-5, 50), breaks=seq(-5,50,5), expand = c(0,0)) +
  scale_y_continuous(limits=c(0,100), breaks=seq(0,100,5), expand = c(0,0)) +
  labs(title="Hubungan antara Suhu Udara dan Kelembaban Udara") + 
  labs(x = xlabsuhu_rh, y="Kelembaban (%)", caption = "Teguh Prasetyo") +
  theme(plot.title=element_text(hjust=0.5)) +
  theme(axis.line=element_line(color="black")) +
  theme(plot.caption = element_text(color = "blue", face = "italic", size = 8, hjust = 1))
g_suhurh
## `geom_smooth()` using formula 'y ~ x'

Dari grafik diagram pencar terlihat jelas bahwa dengan semakin meningkatnya suhu udara maka akan menurunkan kelembaban udara dengan R2 0.33, artinya 33% kelembaban udara dipengaruhi oleh suhu udara.

4.1.4 Sebaran Kadar CO dan NO2 Setiap Jam

# Persiapan Data Time untuk Membuat Boxplot

udara$Time <- hour(udara$Time)
head(udara)
# Membuat boxplot
level_comod <- 2.1
level_copoor <- 10

g_boxco <- ggplot(data=udara, aes(x=as.factor(Time), y=CO)) +
        geom_boxplot(fill = rainbow(24), alpha=0.5) +
        geom_hline(yintercept=level_comod, linetype="dashed", color = "orange") +
        geom_hline(yintercept=level_copoor, linetype="dashed", color = "red") +
        scale_y_continuous(limits=c(0,14), breaks=seq(0,14,2), expand = c(0,0)) +
        labs(title="Variasi Kadar CO pada Setiap Jam") +
        labs(x="Waktu (Jam)", y="Kadar CO (mg/m3)", caption = "Teguh Prasetyo") +
        theme(legend.title = element_text(size=17), legend.text = element_text(size=17)) +
        theme(plot.title=element_text(hjust=0.5)) +
        theme(axis.line=element_line(color="black")) +
        theme(plot.caption = element_text(color = "blue", face = "italic", size = 8, hjust = 1))
g_boxco

Dari grafik di atas terlihat bahwa kadar polutan dari CO yang terendah pada pukul 3-5 dini hari, kemudian beranjak naik seiring aktifitas manusia di pagi hari pada saat berangkat ke kantor (pukul 8-10) dan pada jam pulang kantor (pukul 18-20). Mulai pukul 8, kadar CO berada di atas ambang polusi level moderate (garis putus-putus kuning) dan di bawah level poor (garis putus-putus merah) kecuali pada beberapa kondisi di pukul 18-20, beberapa data berada di atas level poor.

# Membuat boxplot

level_nomod <- 81
level_nopoor <- 181

g_boxno <- ggplot(data=udara, aes(x=as.factor(Time), y=NO2)) +
        geom_boxplot(fill = rainbow(24), alpha = 0.5) +
        geom_hline(yintercept=level_nomod, linetype="dashed", color = "orange") +
        geom_hline(yintercept=level_nopoor, linetype="dashed", color = "red") +
        scale_y_continuous(limits=c(0,350), breaks=seq(0,350,20), expand = c(0,0)) +
        labs(title="Variasi Kadar NO2 pada Setiap Jam") +
        labs(x="Waktu (Jam)", y="Kadar NO2 (microg/m3)", caption = "Teguh Prasetyo") +
        theme(legend.title = element_text(size=17), legend.text = element_text(size=17)) +
        theme(plot.title=element_text(hjust=0.5)) +
        theme(axis.line=element_line(color="black")) +
        theme(plot.caption = element_text(color = "blue", face = "italic", size = 8, hjust = 1))
g_boxno

Dari grafik di atas telihat bahwa trend kadar NO2 hampir sama dengan trend kadar CO, dimana kadar NO2 terendah pada pukul 4-5 dini hari, kemudian beranjak naik seiring aktifitas manusia. Terlihat kadar NO2 tinggi pada pagi hari dari pukul 9-11 dan menjapai tertinggi pada pukul 18-20. Mayoritas kadar NO2 berada di level Moderate (garis putus-putus orange) hingga ke level poor (garis putus-putus merah). Banyak juga kondisi dimana kadar NO2 berada di atas level poor terutama mulai pukul 8-23 dan juga pada dini hari di pukul 0-2 dini hari.

4.1.5 Trend Kadar CO dan NO2 Selama Setahun

Berikut ini adalah trend kadar CO selama setahun.

g_co <- ggplot(data = udara, aes(x = Date, y = CO)) +
          geom_line(col = "black") +
          geom_point(col= "black", pch=19, alpha=0.5, size = 0.8) +
          scale_x_date(breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")),
                                                     to = max(as.Date("2005-04-04")),
                                                     by = "30 days"),
                       minor_breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")),
                                                           to = max(as.Date("2005-04-04")),
                                                           by = "15 days"),
                       date_labels = "%Y/%m/%d") +
          scale_y_continuous(limits=c(0, 12), breaks=seq(0,12,1), expand = c(0,0)) +
          labs(title = "Trend Kadar CO di Udara Selama Setahun di Italy",
               x = "Bulan/Tahun", y="Kadar CO (mg/m3)", caption = "Teguh Prasetyo") +
          theme(legend.position = "none") +
          theme(plot.title=element_text(hjust=0.5)) +
          theme(axis.line=element_line(color="black")) +
          theme(axis.text.x = element_text(angle=45, vjust=0.6)) +
          theme(plot.caption = element_text(color = "blue", face = "italic", size = 8, hjust = 1))

# Pemberian Label untuk Plot Animasi
g_colabel <- g_co + theme(legend.position = "none") +
    geom_label(aes(x = Date, y=CO, label="CO"), nudge_x = 10, size=4, hjust=0)


# Membuat Animated Line Plot
animate(g_colabel + transition_reveal(Date), nframes = 100, fps= 4,
    height = 12, width = 30, units = "cm", res = 150,
    renderer = gifski_renderer(loop = FALSE))

Berikut ini adalah trend kadar NO2 selama setahun.

g_no2 <- ggplot(data = udara, aes(x = Date, y = NO2)) +
          geom_line(col = "brown") +
          geom_point(col= "brown", pch=19, alpha=0.5, size = 0.8) +
          scale_x_date(breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")),
                                                     to = max(as.Date("2005-04-04")),
                                                     by = "30 days"),
                       minor_breaks = function(x) seq.Date(from = min(as.Date("2004-03-10")),
                                                           to = max(as.Date("2005-04-04")),
                                                           by = "15 days"),
                       date_labels = "%Y/%m/%d") +
          scale_y_continuous(limits=c(0, 350), breaks=seq(0,350,20), expand = c(0,0)) +
          labs(title = "Trend Kadar NO2 di Udara Selama Setahun di Italy",
               x = "Bulan/Tahun", y="Kadar NO2 (microg/m3)", caption = "Teguh Prasetyo") +
          theme(legend.position = "none") +
          theme(plot.title=element_text(hjust=0.5)) +
          theme(axis.line=element_line(color="black")) +
          theme(axis.text.x = element_text(angle=45, vjust=0.6)) +
          theme(plot.caption = element_text(color = "blue", face = "italic", size = 8, hjust = 1))

# Pemberian Label untuk Plot Animasi
g_no2label <- g_no2 + theme(legend.position = "none") +
    geom_label(aes(x = Date, y=NO2, label="NO2"), nudge_x = 10, size=4, hjust=0)


# Membuat Animated Line Plot
animate(g_no2label + transition_reveal(Date), nframes = 100, fps= 4,
    height = 12, width = 30, units = "cm", res = 150,
    renderer = gifski_renderer(loop = FALSE))

5. Kesimpulan

Dari visualisasi data dan analisis regresi di atas, terlihat bahwa suhu udara minimum pada -1.90oC dan maksimum pada 44,6oC. Kemudian kelembaban dipengaruhi oleh suhu udara sebesar 33%. Kadar CO dan NO2 terendah pada pukul 3-5 dini hari dimana aktifitas manusia sangat rendah dalam menggunakan kendaraan bermotor, kemudian kadar CO dan NO2 beranjak naik seiring dengan aktifitas manusia dengan peak berada pada pagi hari dan sore hingga malam hari pada waktu transportasi tinggi saat orang-orang berangkat dan pulang kerja.