Latar belakang dari pengerjaan analisis ini muncul setelah mendengar obrolan tentang keluhan ibu bersama dengan para tetangga karena tingginya harga bahan pangan khususnya bumbu masakan utama orang Indonesia seperti cabai, bawang dan daging sapi menjelang Hari Natal, Tahun Baru, serta Hari Raya Lebaran.

Tujuan utama dari analisis ini adalah mencoba untuk membantu para ibu - ibu khususnya yang berdomisili di Kota Bandung mendapatkan informasi terkait pola pergerakan harga pangan serta memberikan rekomendasi perkiraan kapan sebaiknya bahan pangan dibeli menjelang Hari Natal & Tahun Baru maupun Hari Raya Lebaran.


Data Wrangling

Dataset harga pangan Kota Bandung ini diperoleh dari website hargapangan.id yang sebelumnya telah saya lakukan transformasi menggunakan Python Pandas serta tersedia di repository Github saya.

df <- read.csv("food_prices.csv")
head(df)
##      tanggal beras beras_kb1 beras_kb2 beras_km1 beras_km2 beras_ks1 beras_ks2
## 1 04/09/2017 11900     11150     10500     12200     11400     13000     13000
## 2 05/09/2017 11900     11150     10500     12200     11400     13000     13000
## 3 06/09/2017 11900     11150     10500     12200     11400     13000     13000
## 4 07/09/2017 11900     11150     10500     12200     11400     13000     13000
## 5 08/09/2017 11900     11150     10500     12200     11400     13000     13000
## 6 11/09/2017 11900     11150     10500     12200     11400     13000     13000
##   daging_ayam daging_ayam_rs daging_sapi daging_sapi_k1 daging_sapi_k2
## 1       35000          35000      145000         150000         140000
## 2       33500          33500      145000         150000         140000
## 3       33500          33500      145000         150000         140000
## 4       33500          33500      145000         150000         140000
## 5       33500          33500      145000         150000         140000
## 6       32500          32500      145000         150000         140000
##   telur_ayam telur_ayam_rs bawang_merah bawang_merah_sedang bawang_putih
## 1      21000         21000        29000               29000        30000
## 2      22000         22000        29000               29000        30000
## 3      22000         22000        29000               29000        30000
## 4      21000         21000        29000               29000        30000
## 5      21000         21000        29000               29000        30000
## 6      22000         22000        27500               27500        30000
##   bawang_putih_sedang cabai_merah cabai_merah_besar cabai_merah_keriting
## 1               30000       42500             60000                25000
## 2               30000       38750             52500                25000
## 3               30000       38750             52500                25000
## 4               30000       37500             50000                25000
## 5               30000       37500             50000                25000
## 6               30000       37500             50000                25000
##   cabai_rawit cabai_rawit_hijau cabai_rawit_merah minyak_goreng
## 1       27500             25000             30000         13650
## 2       27500             25000             30000         13650
## 3       27500             25000             30000         13650
## 4       27500             25000             30000         13650
## 5       27500             25000             30000         13650
## 6       26250             25000             27500         13650
##   minyak_goreng_curah minyak_goreng_merk1 minyak_goreng_merk2 gula_pasir
## 1               11500               14500               15000      13900
## 2               11500               14500               15000      13900
## 3               11500               14500               15000      13900
## 4               11500               14500               15000      14250
## 5               11500               14500               15000      14250
## 6               11500               14500               15000      14250
##   gula_pasir_premium gula_pasir_lokal
## 1              13750            14000
## 2              13750            14000
## 3              13750            14000
## 4              14500            14000
## 5              14500            14000
## 6              14500            14000


Eksplorasi Kolom Tanggal


Pengubahan tipe data kolom tanggal

df$tanggal <-dmy(df$tanggal)
head(df$tanggal)
## [1] "2017-09-04" "2017-09-05" "2017-09-06" "2017-09-07" "2017-09-08"
## [6] "2017-09-11"


Rentang tanggal dari dataset ini dimulai dari tanggal 4 September 2017 sampai dengan 30 Desember 2020 dengan total 823 baris data

cat("date range:",first(df$tanggal), "-", last(df$tanggal),
    "\nnrow:",nrow(df))
## date range: 17413 - 18626 
## nrow: 823


Dari hasil penghitungan rentang tanggal awal dan akhir pada dataset, bisa disimpulkan bahwa terdapat data tanggal yang hilang

difftime(last(df$tanggal)+1,first(df$tanggal),units = "day")
## Time difference of 1214 days


Terdapat 392 baris data yang hilang dari dataset dan belum diketahui alasan data tidak tercatat/hilang

date_range <- seq(min(df$tanggal), max(df$tanggal+1), by = 1) 

missing_dates <- as.data.frame( date_range[!date_range %in% df$tanggal])
names(missing_dates)[1] <- "tanggal"
nrow(missing_dates)
## [1] 392


Memasukkan baris data yang hilang ke dalam dataframe

df <- merge(df,
             missing_dates,
             by="tanggal",
             all=TRUE)
df[is.na(df)] <- NA
head(df)
##      tanggal beras beras_kb1 beras_kb2 beras_km1 beras_km2 beras_ks1 beras_ks2
## 1 2017-09-04 11900     11150     10500     12200     11400     13000     13000
## 2 2017-09-05 11900     11150     10500     12200     11400     13000     13000
## 3 2017-09-06 11900     11150     10500     12200     11400     13000     13000
## 4 2017-09-07 11900     11150     10500     12200     11400     13000     13000
## 5 2017-09-08 11900     11150     10500     12200     11400     13000     13000
## 6 2017-09-09  <NA>      <NA>      <NA>      <NA>      <NA>      <NA>      <NA>
##   daging_ayam daging_ayam_rs daging_sapi daging_sapi_k1 daging_sapi_k2
## 1       35000          35000      145000         150000         140000
## 2       33500          33500      145000         150000         140000
## 3       33500          33500      145000         150000         140000
## 4       33500          33500      145000         150000         140000
## 5       33500          33500      145000         150000         140000
## 6        <NA>           <NA>        <NA>           <NA>           <NA>
##   telur_ayam telur_ayam_rs bawang_merah bawang_merah_sedang bawang_putih
## 1      21000         21000        29000               29000        30000
## 2      22000         22000        29000               29000        30000
## 3      22000         22000        29000               29000        30000
## 4      21000         21000        29000               29000        30000
## 5      21000         21000        29000               29000        30000
## 6       <NA>          <NA>         <NA>                <NA>         <NA>
##   bawang_putih_sedang cabai_merah cabai_merah_besar cabai_merah_keriting
## 1               30000       42500             60000                25000
## 2               30000       38750             52500                25000
## 3               30000       38750             52500                25000
## 4               30000       37500             50000                25000
## 5               30000       37500             50000                25000
## 6                <NA>        <NA>              <NA>                 <NA>
##   cabai_rawit cabai_rawit_hijau cabai_rawit_merah minyak_goreng
## 1       27500             25000             30000         13650
## 2       27500             25000             30000         13650
## 3       27500             25000             30000         13650
## 4       27500             25000             30000         13650
## 5       27500             25000             30000         13650
## 6        <NA>              <NA>              <NA>          <NA>
##   minyak_goreng_curah minyak_goreng_merk1 minyak_goreng_merk2 gula_pasir
## 1               11500               14500               15000      13900
## 2               11500               14500               15000      13900
## 3               11500               14500               15000      13900
## 4               11500               14500               15000      14250
## 5               11500               14500               15000      14250
## 6                <NA>                <NA>                <NA>       <NA>
##   gula_pasir_premium gula_pasir_lokal
## 1              13750            14000
## 2              13750            14000
## 3              13750            14000
## 4              14500            14000
## 5              14500            14000
## 6               <NA>             <NA>


Menambahkan kolom nama hari

df$hari <- wday(df$tanggal, label = TRUE,abbr = FALSE)
head(df)
##      tanggal beras beras_kb1 beras_kb2 beras_km1 beras_km2 beras_ks1 beras_ks2
## 1 2017-09-04 11900     11150     10500     12200     11400     13000     13000
## 2 2017-09-05 11900     11150     10500     12200     11400     13000     13000
## 3 2017-09-06 11900     11150     10500     12200     11400     13000     13000
## 4 2017-09-07 11900     11150     10500     12200     11400     13000     13000
## 5 2017-09-08 11900     11150     10500     12200     11400     13000     13000
## 6 2017-09-09  <NA>      <NA>      <NA>      <NA>      <NA>      <NA>      <NA>
##   daging_ayam daging_ayam_rs daging_sapi daging_sapi_k1 daging_sapi_k2
## 1       35000          35000      145000         150000         140000
## 2       33500          33500      145000         150000         140000
## 3       33500          33500      145000         150000         140000
## 4       33500          33500      145000         150000         140000
## 5       33500          33500      145000         150000         140000
## 6        <NA>           <NA>        <NA>           <NA>           <NA>
##   telur_ayam telur_ayam_rs bawang_merah bawang_merah_sedang bawang_putih
## 1      21000         21000        29000               29000        30000
## 2      22000         22000        29000               29000        30000
## 3      22000         22000        29000               29000        30000
## 4      21000         21000        29000               29000        30000
## 5      21000         21000        29000               29000        30000
## 6       <NA>          <NA>         <NA>                <NA>         <NA>
##   bawang_putih_sedang cabai_merah cabai_merah_besar cabai_merah_keriting
## 1               30000       42500             60000                25000
## 2               30000       38750             52500                25000
## 3               30000       38750             52500                25000
## 4               30000       37500             50000                25000
## 5               30000       37500             50000                25000
## 6                <NA>        <NA>              <NA>                 <NA>
##   cabai_rawit cabai_rawit_hijau cabai_rawit_merah minyak_goreng
## 1       27500             25000             30000         13650
## 2       27500             25000             30000         13650
## 3       27500             25000             30000         13650
## 4       27500             25000             30000         13650
## 5       27500             25000             30000         13650
## 6        <NA>              <NA>              <NA>          <NA>
##   minyak_goreng_curah minyak_goreng_merk1 minyak_goreng_merk2 gula_pasir
## 1               11500               14500               15000      13900
## 2               11500               14500               15000      13900
## 3               11500               14500               15000      13900
## 4               11500               14500               15000      14250
## 5               11500               14500               15000      14250
## 6                <NA>                <NA>                <NA>       <NA>
##   gula_pasir_premium gula_pasir_lokal      hari
## 1              13750            14000    Monday
## 2              13750            14000   Tuesday
## 3              13750            14000 Wednesday
## 4              14500            14000  Thursday
## 5              14500            14000    Friday
## 6               <NA>             <NA>  Saturday


Data pada hari Sabtu dan Minggu memiliki nilai NA terbanyak dan dapat disimpulkan karena disebabkan oleh hari libur kerja sehingga tidak dilakukan pencatatan data

dataNA <- data.frame("tanggal"=df[is.na(df$beras),]$tanggal,
                      "hari"=df[is.na(df$beras),]$hari)
summary(dataNA)
##     tanggal                  hari    
##  Min.   :2017-09-09   Sunday   :173  
##  1st Qu.:2018-07-12   Monday   :  5  
##  Median :2019-05-11   Tuesday  : 10  
##  Mean   :2019-05-16   Wednesday:  9  
##  3rd Qu.:2020-03-30   Thursday : 10  
##  Max.   :2020-12-31   Friday   : 12  
##                       Saturday :173


Baris data dengan nilai NA selain hari Sabtu dan Minggu terjadi karena disebabkan oleh hari libur nasional

Weekend <- c("Saturday","Sunday")
head(dataNA[!(dataNA$hari %in% Weekend),]$tanggal)
## [1] "2017-09-21" "2017-12-25" "2017-12-26" "2018-01-01" "2018-02-16"
## [6] "2018-03-30"


Eksplorasi Kolom Harga Pangan


Terdapat nilai string ‘-’ (minus) yang perlu diubah menjadi NA

unique(df$beras)
##  [1] "11900" NA      "12150" "-"     "12300" "13300" "12050" "12500" "12250"
## [10] "12400" "12450" "12600" "12650" "12750" "12700" "12550" "12350" "12100"
## [19] "12000" "12200" "11850" "11650" "11600" "11400" "11550" "11950" "11750"
## [28] "11350" "11450" "11500"


Pengubahan tipe data kolom harga pangan menjadi integer
dengan pengubahan tipe data menjadi integer maka nilai selain angka akan berubah secara paksa menjadi nilai NA

excludeDates <- sapply(df, class) != "Date"
suppressWarnings(df[, excludeDates] <- lapply(df[, excludeDates], as.integer))
head(df)
##      tanggal beras beras_kb1 beras_kb2 beras_km1 beras_km2 beras_ks1 beras_ks2
## 1 2017-09-04 11900     11150     10500     12200     11400     13000     13000
## 2 2017-09-05 11900     11150     10500     12200     11400     13000     13000
## 3 2017-09-06 11900     11150     10500     12200     11400     13000     13000
## 4 2017-09-07 11900     11150     10500     12200     11400     13000     13000
## 5 2017-09-08 11900     11150     10500     12200     11400     13000     13000
## 6 2017-09-09    NA        NA        NA        NA        NA        NA        NA
##   daging_ayam daging_ayam_rs daging_sapi daging_sapi_k1 daging_sapi_k2
## 1       35000          35000      145000         150000         140000
## 2       33500          33500      145000         150000         140000
## 3       33500          33500      145000         150000         140000
## 4       33500          33500      145000         150000         140000
## 5       33500          33500      145000         150000         140000
## 6          NA             NA          NA             NA             NA
##   telur_ayam telur_ayam_rs bawang_merah bawang_merah_sedang bawang_putih
## 1      21000         21000        29000               29000        30000
## 2      22000         22000        29000               29000        30000
## 3      22000         22000        29000               29000        30000
## 4      21000         21000        29000               29000        30000
## 5      21000         21000        29000               29000        30000
## 6         NA            NA           NA                  NA           NA
##   bawang_putih_sedang cabai_merah cabai_merah_besar cabai_merah_keriting
## 1               30000       42500             60000                25000
## 2               30000       38750             52500                25000
## 3               30000       38750             52500                25000
## 4               30000       37500             50000                25000
## 5               30000       37500             50000                25000
## 6                  NA          NA                NA                   NA
##   cabai_rawit cabai_rawit_hijau cabai_rawit_merah minyak_goreng
## 1       27500             25000             30000         13650
## 2       27500             25000             30000         13650
## 3       27500             25000             30000         13650
## 4       27500             25000             30000         13650
## 5       27500             25000             30000         13650
## 6          NA                NA                NA            NA
##   minyak_goreng_curah minyak_goreng_merk1 minyak_goreng_merk2 gula_pasir
## 1               11500               14500               15000      13900
## 2               11500               14500               15000      13900
## 3               11500               14500               15000      13900
## 4               11500               14500               15000      14250
## 5               11500               14500               15000      14250
## 6                  NA                  NA                  NA         NA
##   gula_pasir_premium gula_pasir_lokal hari
## 1              13750            14000    2
## 2              13750            14000    3
## 3              13750            14000    4
## 4              14500            14000    5
## 5              14500            14000    6
## 6                 NA               NA    7

Persentase Nilai NA Kolom Harga Pangan

Persentase nilai NA pada kolom harga pangan sebesar 33.1%

options(digits=3)
NaPercentage <- as.data.frame(apply(df, 2, function(col)sum(is.na(col))/length(col)*100))
names(NaPercentage)[1] <- "Persentase"
NaPercentage
##                      Persentase
## tanggal                     0.0
## beras                      33.1
## beras_kb1                  33.1
## beras_kb2                  33.1
## beras_km1                  33.1
## beras_km2                  33.1
## beras_ks1                  33.1
## beras_ks2                  33.1
## daging_ayam                33.1
## daging_ayam_rs             33.1
## daging_sapi                33.1
## daging_sapi_k1             33.1
## daging_sapi_k2             33.1
## telur_ayam                 33.1
## telur_ayam_rs              33.1
## bawang_merah               33.1
## bawang_merah_sedang        33.1
## bawang_putih               33.1
## bawang_putih_sedang        33.1
## cabai_merah                33.1
## cabai_merah_besar          33.1
## cabai_merah_keriting       33.1
## cabai_rawit                33.1
## cabai_rawit_hijau          33.1
## cabai_rawit_merah          33.1
## minyak_goreng              33.1
## minyak_goreng_curah        33.1
## minyak_goreng_merk1        33.1
## minyak_goreng_merk2        33.1
## gula_pasir                 33.1
## gula_pasir_premium         33.1
## gula_pasir_lokal           33.1
## hari                        0.0

Pengisian Nilai NA

Pengisian nilai NA (missing values) pada kolom harga pangan menggunakan nilai harga hari sebelumnya

df <- na.locf(na.locf(df), fromLast = TRUE)
colSums(is.na(df)) == 0
##              tanggal                beras            beras_kb1 
##                 TRUE                 TRUE                 TRUE 
##            beras_kb2            beras_km1            beras_km2 
##                 TRUE                 TRUE                 TRUE 
##            beras_ks1            beras_ks2          daging_ayam 
##                 TRUE                 TRUE                 TRUE 
##       daging_ayam_rs          daging_sapi       daging_sapi_k1 
##                 TRUE                 TRUE                 TRUE 
##       daging_sapi_k2           telur_ayam        telur_ayam_rs 
##                 TRUE                 TRUE                 TRUE 
##         bawang_merah  bawang_merah_sedang         bawang_putih 
##                 TRUE                 TRUE                 TRUE 
##  bawang_putih_sedang          cabai_merah    cabai_merah_besar 
##                 TRUE                 TRUE                 TRUE 
## cabai_merah_keriting          cabai_rawit    cabai_rawit_hijau 
##                 TRUE                 TRUE                 TRUE 
##    cabai_rawit_merah        minyak_goreng  minyak_goreng_curah 
##                 TRUE                 TRUE                 TRUE 
##  minyak_goreng_merk1  minyak_goreng_merk2           gula_pasir 
##                 TRUE                 TRUE                 TRUE 
##   gula_pasir_premium     gula_pasir_lokal                 hari 
##                 TRUE                 TRUE                 TRUE

Data Exploration

fokus ke data 2018 - 2020 dengan data harga daging_ayam, daging_sapi, telur_ayam, bawang_merah, bawang_putih, cabai_merah

catatan: - cek harga tertinggi per tahun disetiap bahan pangan - cek pola harga tertinggi setiap tahun disetiap bahan pangan - korelasi antar bahan pangan - cek rata2 harga tertinggi pada bulan apa disetiap tahunnya - harga terendah sebelum hari lebaran,natal,tahun baru untuk membeli bahan pangan - berapa persen kenaikan harga pangan yang tertinggi

pangan <- df %>% 
  select(tanggal,
         daging_ayam,
         daging_sapi, 
         telur_ayam, 
         bawang_merah,
         bawang_putih, 
         cabai_merah,
         cabai_rawit) %>% 
  subset((tanggal >= "2018-01-01") & (tanggal <= "2020-12-31"))


ggplot(pangan, aes(x=tanggal,color=)) +
  geom_line(aes(y = daging_ayam,color = "Daging Ayam")  , size = 1) +
  geom_line(aes(y = telur_ayam,  color = "Telur Ayam"), size = 1) +
  geom_line(aes(y = daging_sapi,   color = "Daging Sapi"), size = 1) +
  geom_line(aes(y = bawang_merah, color = "Bawang Merah"), size = 1) +
  geom_line(aes(y = bawang_putih, color = "Bawang Putih"), size = 1) +
  geom_line(aes(y = cabai_merah,  color = "Cabai Merah" ),size = 1) +
    labs(x = "Tahun",
         y = "Harga",
         title = "Harga Pangan Bulanan Kota Bandung (2018 - 2020)",
         color = "")+
  theme(plot.title = element_text(hjust = 0.5))+
  scale_y_continuous(breaks = seq(10000, 160000, 10000)) +
   scale_x_date(date_breaks = "1 month",
             date_labels = "%b %y")

rata2 harga per bylan

sapi_monthly <- pangan %>%
  mutate(month = floor_date(pangan$tanggal, "month")) %>%
           group_by(month) %>%
           summarize(avg = mean(bawang_merah))

ggplot(sapi_monthly, aes(x=month)) + 
  geom_line(aes(y = avg), color = "darkred")

cabe <- pangan %>%
  mutate(month = floor_date(pangan$tanggal, "month")) %>%
           group_by(month) %>%
           summarize(avg = mean(cabai_merah))

ggplot(cabe, aes(x=month)) + 
  geom_line(aes(y = avg), color = "darkred")

cabe <- pangan %>%
  mutate(month = floor_date(pangan$tanggal, "month")) %>%
           group_by(month) %>%
           summarize(avg = mean(cabai_rawit))

ggplot(cabe, aes(x=month)) + 
  geom_line(aes(y = avg), color = "darkred")

plot(pangan$cabai_merah,pangan$cabai_rawit)
abline(lm(pangan$cabai_rawit ~ pangan$cabai_merah, data = pangan), col = "blue")

sapi_monthly %>% filter(month <= "2020-12-31") %>% 
  arrange(-avg)
## # A tibble: 36 x 2
##    month         avg
##    <date>      <dbl>
##  1 2020-05-01 56258.
##  2 2020-06-01 52917.
##  3 2020-04-01 52100 
##  4 2019-04-01 48333.
##  5 2019-12-01 42065.
##  6 2020-01-01 39758.
##  7 2019-03-01 39323.
##  8 2019-05-01 39306.
##  9 2020-03-01 39258.
## 10 2018-06-01 38700 
## # ... with 26 more rows
sapi_monthly %>% filter(month == "2018-06-13")
## # A tibble: 0 x 2
## # ... with 2 variables: month <date>, avg <dbl>