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.
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
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"
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 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 (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
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>