Mata Kuliah: Manajemen Data Statistika
Proyek UAS – Kelompok 1 (Nabila Syukri - Yani P. Hiola - Mahda Almaidah - Hazelita)

Data diperoleh melalui proses web scraping dari situs lowongan pekerjaan https://www.kalibrr.id. Situs ini menyediakan informasi mengenai berbagai lowongan kerja dari berbagai perusahaan di Indonesia, dengan deskripsi posisi, lokasi, industri, dan persyaratan yang beragam.

Tahapan

  1. Scrapping data dilakukan dengan ekstensi browser Data Miner
  2. Cleaning Data hasil scrapping
  3. Menyimpan data ke MongoDB untuk mempermudah pengelolaan dan pemrosesan data hasil scrapping secara terstruktut
  4. Visualisasi data dengan R

Variabel

Adapun variabel yang berhasil discrapping dan akan diagregasi lalu visualisasi ialah Nama pekerjaan, Perusahaan, Posisi, Gaji, Kota, Status, dan Deadline

Memuat Package

Connect MongoDB

library(mongolite)
## Warning: package 'mongolite' was built under R version 4.4.3
# koneksi R ke mongoatlas
kalibrr <- mongo(collection = "Kalibrr",
              db = "Project_Praktikum_MDS_UAS",
              url = "mongodb+srv://hazelitadwi:Tujuhbelas402@cluster0.kg8jqpb.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0")
kalibrr$find(limit=5)
##                                                            Pekerjaan
## 1 Join Our Team as a Course Consultant at EF English First Surabaya!
## 2                                                    DevOps Engineer
## 3                                       Videographer & Editor Intern
## 4                      Developer Support Engineer  6 Months Contract
## 5                             Relationship Manager Corporate Banking
##                       Nama Perusahaan                       Kota
## 1               English 1 Eduka Group        Surabaya, Indonesia
## 2                Klik Digital Sinergi        Pancoran, Indonesia
## 3 PT Prodia Widyahusada Tbk. (Prodia) Central Jakarta, Indonesia
## 4        Trimegah Sekuritas Indonesia   South Jakarta, Indonesia
## 5            PT Bank Central Asia Tbk Central Jakarta, Indonesia
##                   Gaji    Status                       Posisi         Deadline
## 1 Gaji Tidak Diumumkan Full Time        Lulusan Baru / Junior      19 May 2025
## 2 Gaji Tidak Diumumkan Full Time Supervisor / Asisten Manager 10 February 2025
## 3 Gaji Tidak Diumumkan   Kontrak        Lulusan Baru / Junior 18 December 2025
## 4 Gaji Tidak Diumumkan   Kontrak Supervisor / Asisten Manager     05 July 2025
## 5 Gaji Tidak Diumumkan Full Time        Lulusan Baru / Junior     30 June 2025
##      Bulan
## 1      Mei
## 2 Februari
## 3 Desember
## 4     Juli
## 5     Juni

## Mengubah data menjadi data frame

data <- kalibrr$find()
data_kalibrr <- as.data.frame(data)
#Ubah tipe data
data_kalibrr[] <- lapply(data_kalibrr, function(x) {
  if (is.character(x)) {
    as.factor(x)
  } else {
    x
  }
})
# Display the modified data frame
str(data_kalibrr)
## 'data.frame':    534 obs. of  8 variables:
##  $ Pekerjaan      : Factor w/ 139 levels "[Jendela] Business Development Executive",..: 61 43 137 42 104 118 74 89 36 2 ...
##  $ Nama Perusahaan: Factor w/ 61 levels "Allvacon","Alodokter",..: 11 18 42 60 31 52 34 34 19 36 ...
##  $ Kota           : Factor w/ 41 levels "Bandung Kota, Indonesia",..: 37 27 9 35 9 15 28 34 38 1 ...
##  $ Gaji           : Factor w/ 11 levels "Gaji Tidak Diumumkan",..: 1 1 1 1 1 1 6 9 1 11 ...
##  $ Status         : Factor w/ 3 levels "Freelance","Full Time",..: 2 2 3 3 2 3 2 2 2 2 ...
##  $ Posisi         : Factor w/ 4 levels "Lulusan Baru / Junior",..: 1 4 1 4 1 4 1 1 4 4 ...
##  $ Deadline       : Factor w/ 150 levels "01 July 2025",..: 118 23 113 13 143 19 150 150 29 2 ...
##  $ Bulan          : Factor w/ 11 levels "Agustus","April",..: 8 4 3 5 6 8 8 8 6 6 ...
head(data_kalibrr)
##                                                            Pekerjaan
## 1 Join Our Team as a Course Consultant at EF English First Surabaya!
## 2                                                    DevOps Engineer
## 3                                       Videographer & Editor Intern
## 4                      Developer Support Engineer  6 Months Contract
## 5                             Relationship Manager Corporate Banking
## 6                                       Springboot Backend Developer
##                       Nama Perusahaan                       Kota
## 1               English 1 Eduka Group        Surabaya, Indonesia
## 2                Klik Digital Sinergi        Pancoran, Indonesia
## 3 PT Prodia Widyahusada Tbk. (Prodia) Central Jakarta, Indonesia
## 4        Trimegah Sekuritas Indonesia   South Jakarta, Indonesia
## 5            PT Bank Central Asia Tbk Central Jakarta, Indonesia
## 6                          Quantyc.ai Jakarta Selatan, Indonesia
##                   Gaji    Status                       Posisi         Deadline
## 1 Gaji Tidak Diumumkan Full Time        Lulusan Baru / Junior      19 May 2025
## 2 Gaji Tidak Diumumkan Full Time Supervisor / Asisten Manager 10 February 2025
## 3 Gaji Tidak Diumumkan   Kontrak        Lulusan Baru / Junior 18 December 2025
## 4 Gaji Tidak Diumumkan   Kontrak Supervisor / Asisten Manager     05 July 2025
## 5 Gaji Tidak Diumumkan Full Time        Lulusan Baru / Junior     30 June 2025
## 6 Gaji Tidak Diumumkan   Kontrak Supervisor / Asisten Manager      08 May 2025
##      Bulan
## 1      Mei
## 2 Februari
## 3 Desember
## 4     Juli
## 5     Juni
## 6      Mei

Visualisasi

Jumlah lowongan berdasarkan posisi

posisi <- '[{
  "$match": { "Posisi": { "$ne": null } }
}, {
  "$group": {
    "_id": "$Posisi",
    "jumlah_lowongan": { "$sum": 1 }
  }
}, {
  "$project": {
    "Posisi": "$_id",
    "jumlah_lowongan": 1,
    "_id": 0
  }
}]'

data_posisi <- kalibrr$aggregate(posisi)
library(ggplot2)
library(dplyr)

ggplot(data_posisi, aes(x = reorder(Posisi, jumlah_lowongan), y = jumlah_lowongan, fill = Posisi)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  geom_text(aes(label = jumlah_lowongan), hjust = 0) +
  coord_flip() +
  labs(title = "Jumlah Lowongan berdasarkan Posisi",
       x = "Posisi",
       y = "Jumlah Lowongan") +
  theme_minimal()

Jumlah lowongan berdasarkan status

pipeline_status <- '[{
  "$match": { "Status": { "$ne": null } }
}, {
  "$group": {
    "_id": "$Status",
    "jumlah_lowongan": { "$sum": 1 }
  }
}, {
  "$project": {
    "Status": "$_id",
    "jumlah_lowongan": 1,
    "_id": 0
  }
}]'

data_status <- kalibrr$aggregate(pipeline_status)
ggplot(data_status, aes(x = reorder(Status, jumlah_lowongan), y = jumlah_lowongan, fill = Status)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  geom_text(aes(label = jumlah_lowongan), hjust = 0) +
  coord_flip() +
  labs(title = "Jumlah Lowongan berdasarkan Status",
       x = "Status",
       y = "Jumlah Lowongan") +
  theme_minimal()

Jumlah lowongan berdasarkan posisi dan status

pipeline_posisi_status <- '[{
  "$match": {
    "Posisi": { "$ne": null },
    "Status": { "$in": [ "Freelance", "Full Time", "Kontrak" ] }
  }
}, {
  "$group": {
    "_id": { "Posisi": "$Posisi", "Status": "$Status" },
    "jumlah_lowongan": { "$sum": 1 }
  }
}, {
  "$project": {
    "Posisi": "$_id.Posisi",
    "Status": "$_id.Status",
    "jumlah_lowongan": 1,
    "_id": 0
  }
}]'

data_posisi_status <- kalibrr$aggregate(pipeline_posisi_status)
ggplot(data_posisi_status, aes(x = reorder(Posisi, jumlah_lowongan), y = jumlah_lowongan, fill = Status)) +
  geom_bar(stat = "identity", position = "stack") +
  geom_text(aes(label = jumlah_lowongan), position = position_stack(vjust = 0.5), size = 3, color = "white") +
  coord_flip() +
  labs(title = "Jumlah Lowongan berdasarkan Posisi dan Status",
       x = "Posisi",
       y = "Jumlah Lowongan",
       fill = "Status") +
  theme_minimal()

Trend jumlah lowongan per bulan

pipeline_bulan <- '[{
  "$match": { "Bulan": { "$ne": null } }
}, {
  "$group": {
    "_id": "$Bulan",
    "jumlah_lowongan": { "$sum": 1 }
  }
}, {
  "$project": {
    "Bulan": "$_id",
    "jumlah_lowongan": 1,
    "_id": 0
  }
}]'

data_bulan <- kalibrr$aggregate(pipeline_bulan)
library(forcats)

# Susun nama bulan secara manual (jika diperlukan)
bulan_order <- c("Januari", "Februari", "Maret", "April", "Mei", "Juni",
                 "Juli", "Agustus", "September", "Oktober", "November", "Desember")

data_bulan$Bulan <- factor(data_bulan$Bulan, levels = bulan_order)

ggplot(data_bulan, aes(x = Bulan, y = jumlah_lowongan, fill = Bulan)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = jumlah_lowongan), vjust = -0.5) +
  labs(title = "Jumlah Lowongan per Bulan",
       x = "Bulan",
       y = "Jumlah Lowongan") +
  theme_minimal()

ggplot(data_bulan, aes(x = Bulan, y = jumlah_lowongan, group = 1)) +
  geom_point(size = 3, color = "steelblue") +  # Titik
  geom_line(color = "steelblue", linewidth = 1) +  # Garis penghubung antar titik
  geom_text(aes(label = jumlah_lowongan), vjust = -0.8, size = 3.5) +
  labs(title = "Tren Jumlah Lowongan per Bulan",
       x = "Bulan",
       y = "Jumlah Lowongan") +
  theme_minimal() +
  scale_x_discrete(limits = bulan_order)  # agar urutan bulan tetap terjaga

library(dplyr)

# Filter untuk bulan Juni dan hitung frekuensi pekerjaan
pekerjaan_juni <- data_kalibrr %>%
  filter(Bulan == "Juni") %>%
  count(Pekerjaan, sort = TRUE)

# Lihat 10 pekerjaan teratas di bulan Juni
head(pekerjaan_juni, 10)
##                                                               Pekerjaan n
## 1                       Business Development Internship Corporate IT&IS 9
## 2                                 Content Writer Travel Food KOMPAS.com 9
## 3                        Primary Teacher at Multimedia Nusantara School 9
## 4                                     Assistant Editor Gramedia Edukasi 6
## 5                                             Assistant Editor Grasindo 6
## 6  CENTER FOR SUSTAINABILITY OFFICER – UNIVERSITAS MULTIMEDIA NUSANTARA 6
## 7                                                 MUA Intern KOMPAS.com 6
## 8                                          Software Engineer Kompas.com 6
## 9                         Store Superintendent Gramedia Daan Mogot Mall 6
## 10                         Store Superintendent Gramedia Dumai Citimall 6
library(ggplot2)

top10_juni <- pekerjaan_juni %>% top_n(10, n)

ggplot(top10_juni, aes(x = reorder(Pekerjaan, n), y = n, fill = Pekerjaan)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = n), hjust = -0.2) +
  coord_flip() +
  labs(title = "Top 10 Pekerjaan di Bulan Juni",
       x = "Pekerjaan",
       y = "Jumlah Lowongan") +
  theme_minimal()

Perusahaan Top 10 dengan Jumlah lowongan terbanyak

pipeline_perusahaan <- '[{
  "$match": { "Nama Perusahaan": { "$ne": null } }
}, {
  "$group": {
    "_id": "$Nama Perusahaan",
    "jumlah_lowongan": { "$sum": 1 }
  }
}, {
  "$sort": { "jumlah_lowongan": -1 }
}, {
  "$limit": 10
}, {
  "$project": {
    "NamaPerusahaan": "$_id",
    "jumlah_lowongan": 1,
    "_id": 0
  }
}]'

data_perusahaan <- kalibrr$aggregate(pipeline_perusahaan)
ggplot(data_perusahaan, aes(x = reorder(NamaPerusahaan, jumlah_lowongan), 
                            y = jumlah_lowongan, fill = NamaPerusahaan)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = jumlah_lowongan), hjust = 1) +
  coord_flip() +
  labs(title = "Top 10 Perusahaan dengan Jumlah Lowongan Terbanyak",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan") +
  theme_minimal()

Top 10 Perusahaan berdasarkan posisi

pipeline <- '[{
  "$match": {
    "Posisi": { "$ne": null },
    "Nama Perusahaan": { "$ne": null }
  }
}, {
  "$group": {
    "_id": { "Nama Perusahaan": "$Nama Perusahaan", "Posisi": "$Posisi" },
    "jumlah_lowongan": { "$sum": 1 }
  }
}, {
  "$project": {
    "Nama Perusahaan": "$_id.Nama Perusahaan",
    "Posisi": "$_id.Posisi",
    "jumlah_lowongan": 1,
    "_id": 0
  }
}]'

# Eksekusi pipeline
agg_posisi_perusahaan <- kalibrr$aggregate(pipeline)
library(dplyr)

# Ambil Top 10 perusahaan dengan jumlah lowongan terbanyak (secara keseluruhan)
top10_perusahaan <- agg_posisi_perusahaan %>%
  group_by(`Nama Perusahaan`) %>%
  summarise(total = sum(jumlah_lowongan)) %>%
  arrange(desc(total)) %>%
  slice_head(n = 10) %>%
  pull(`Nama Perusahaan`)

# Filter hanya data dari perusahaan top 10 tadi
agg_top10_posisi_perusahaan <- agg_posisi_perusahaan %>%
  filter(`Nama Perusahaan` %in% top10_perusahaan)
library(ggplot2)

ggplot(agg_top10_posisi_perusahaan,
       aes(x = reorder(`Nama Perusahaan`, jumlah_lowongan, sum),
           y = jumlah_lowongan,
           fill = Posisi)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  labs(title = "Top 10 Perusahaan dengan Lowongan Terbanyak Berdasarkan Posisi",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan",
       fill = "Posisi") +
  theme_minimal()

Lowongan Berdasarkan Kota

library(dplyr)
library(stringr)

data_kalibrr_cleaned <- data_kalibrr %>%
  mutate(Kota = case_when(
    # Jakarta - dengan pembagian wilayah
    str_detect(Kota, regex("South Jakarta|Jakarta Selatan", ignore_case = TRUE)) ~ "Jakarta Selatan",
    str_detect(Kota, regex("North Jakarta|Jakarta Utara", ignore_case = TRUE)) ~ "Jakarta Utara",
    str_detect(Kota, regex("West Jakarta|Jakarta Barat", ignore_case = TRUE)) ~ "Jakarta Barat",
    str_detect(Kota, regex("East Jakarta|Jakarta Timur", ignore_case = TRUE)) ~ "Jakarta Timur",
    str_detect(Kota, regex("Central Jakarta|Jakarta Pusat", ignore_case = TRUE)) ~ "Jakarta Pusat",
    str_detect(Kota, regex("Jakarta", ignore_case = TRUE)) ~ "Jakarta",  # fallback
    
    # Bandung
    str_detect(Kota, regex("Bandung", ignore_case = TRUE)) ~ "Bandung",
    
    # Bogor
    str_detect(Kota, regex("Bogor", ignore_case = TRUE)) ~ "Bogor",
    
    # Bekasi
    str_detect(Kota, regex("Bekasi", ignore_case = TRUE)) ~ "Bekasi",
    
    # Tangerang
    str_detect(Kota, regex("Tangerang", ignore_case = TRUE)) ~ "Tangerang",
    
    # Surabaya
    str_detect(Kota, regex("Surabaya", ignore_case = TRUE)) ~ "Surabaya",
    
    # Banjarmasin
    str_detect(Kota, regex("Banjarmasin", ignore_case = TRUE)) ~ "Banjarmasin",
    
    # Banyumas
    str_detect(Kota, regex("Banyumas", ignore_case = TRUE)) ~ "Banyumas",
    
    # Depok
    str_detect(Kota, regex("Depok", ignore_case = TRUE)) ~ "Depok",
    
    # Denpasar
    str_detect(Kota, regex("Denpasar", ignore_case = TRUE)) ~ "Denpasar",
    
    # Kota lainnya tetap
    TRUE ~ as.character(Kota)
  ))
library(dplyr)

top_kota <- data_kalibrr_cleaned %>%
  filter(!is.na(Kota)) %>%
  group_by(Kota) %>%
  summarise(jumlah_lowongan = n()) %>%
  arrange(desc(jumlah_lowongan)) %>%
  slice_head(n = 10)
library(ggplot2)

ggplot(top_kota, aes(x = reorder(Kota, jumlah_lowongan), y = jumlah_lowongan, fill = Kota)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = jumlah_lowongan), hjust = 0, size = 4) +
  coord_flip() +
  labs(title = "Top 10 Kota dengan Jumlah Lowongan Terbanyak",
       x = "Kota",
       y = "Jumlah Lowongan") +
  theme_minimal()

Perusahaan di Tangerang

library(dplyr)

perusahaan_tangerang <- data_kalibrr_cleaned %>%
  filter(Kota == "Tangerang") %>%
  group_by(`Nama Perusahaan`) %>%
  summarise(jumlah_lowongan = n()) %>%
  arrange(desc(jumlah_lowongan))

library(ggplot2)

ggplot(perusahaan_tangerang, aes(x = reorder(`Nama Perusahaan`, jumlah_lowongan),
                                  y = jumlah_lowongan,
                                  fill = `Nama Perusahaan`)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = jumlah_lowongan), hjust = -0.2, size = 4) +
  coord_flip() +
  labs(title = "Jumlah Lowongan di Tangerang per Perusahaan",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan") +
  theme_minimal()

library(dplyr)

perusahaan_posisi_tangerang <- data_kalibrr_cleaned %>%
  filter(Kota == "Tangerang") %>%
  group_by(`Nama Perusahaan`, Posisi) %>%
  summarise(jumlah_lowongan = n(), .groups = "drop") %>%
  arrange(desc(jumlah_lowongan))
library(ggplot2)

ggplot(perusahaan_posisi_tangerang,
       aes(x = Posisi, y = `Nama Perusahaan`, fill = jumlah_lowongan)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  labs(title = "Jumlah Lowongan per Perusahaan dan Posisi di Tangerang",
       x = "Posisi",
       y = "Nama Perusahaan",
       fill = "Jumlah Lowongan") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

ggplot(perusahaan_posisi_tangerang,
       aes(x = reorder(`Nama Perusahaan`, jumlah_lowongan, sum),
           y = jumlah_lowongan, fill = Posisi)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  labs(title = "Lowongan di Tangerang berdasarkan Perusahaan dan Posisi",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan",
       fill = "Posisi") +
  theme_minimal()

Heatmap jumlah lowongan per status di 10 Kota teratas

data_kota_status <- data_kalibrr_cleaned %>%
  filter(!is.na(Kota), !is.na(Status)) %>%
  group_by(Kota, Status) %>%
  summarise(jumlah_lowongan = n(), .groups = "drop")

top_kota <- data_kota_status %>%
  group_by(Kota) %>%
  summarise(total = sum(jumlah_lowongan)) %>%
  arrange(desc(total)) %>%
  slice_head(n = 10) %>%
  pull(Kota)

data_kota_status_top <- data_kota_status %>%
  filter(Kota %in% top_kota)

ggplot(data_kota_status_top, aes(x = Status, y = reorder(Kota, jumlah_lowongan), fill = jumlah_lowongan)) +
  geom_tile(color = "white") +
  geom_text(aes(label = jumlah_lowongan), color = "black", size = 3) +
  scale_fill_gradient(low = "#e0f3f8", high = "#08306b") +
  labs(title = "Heatmap Jumlah Lowongan berdasarkan Kota dan Status",
       x = "Status",
       y = "Kota",
       fill = "Jumlah") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Heatmap jumlah lowongan berdasarkan posisi dan status

library(ggplot2)

ggplot(data_posisi_status, aes(x = Status, y = reorder(Posisi, jumlah_lowongan), fill = jumlah_lowongan)) +
  geom_tile(color = "white") +
  geom_text(aes(label = jumlah_lowongan), color = "black", size = 3) +
  scale_fill_gradient(low = "lightblue", high = "#08305b") +
  labs(title = "Heatmap Jumlah Lowongan berdasarkan Posisi dan Status",
       x = "Status",
       y = "Posisi",
       fill = "Jumlah") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

# Membersihkan Kolom Gaji
# Kolom 'Gaji' kemungkinan berisi teks seperti "Rp 12.000.000" atau "Gaji Tidak Diumumkan"
data_kalibrr_cleaned <- data_kalibrr %>%
  mutate(
    Gaji_Numerik = str_trim(Gaji),  # Hilangkan spasi depan/belakang
    Gaji_Numerik = ifelse(
      str_detect(Gaji_Numerik, regex("tidak diumumkan", ignore_case = TRUE)) | Gaji_Numerik == "", 
      NA, 
      Gaji_Numerik
    ),
    Gaji_Numerik = str_replace_all(Gaji_Numerik, "Rp\\s*", ""),  # Hapus "Rp" dan spasi setelahnya
    Gaji_Numerik = str_replace_all(Gaji_Numerik, "\\.", ""),      # Hapus titik
    Gaji_Numerik = suppressWarnings(as.numeric(Gaji_Numerik))     # Konversi jadi numerik
  )

# Cek hasil
#data_kalibrr_cleaned %>% select(Gaji, Gaji_Numerik)
#summary(data_kalibrr_cleaned$Gaji_Numerik)
#unique(data_kalibrr_cleaned$Gaji_Numerik)
# Hitung jumlah baris dengan gaji diumumkan vs tidak diumumkan
gaji_summary <- data_kalibrr_cleaned %>%
  mutate(Status_Gaji = ifelse(is.na(Gaji_Numerik), "Tidak Diumumkan", "Diumumkan")) %>%
  count(Status_Gaji)

Jumlah lowongan berdasrkan gaji diumumkan dan tidak

# Bar plot
plot_gaji_bar <- ggplot(gaji_summary, aes(x = Status_Gaji, y = n, fill = Status_Gaji)) +
  geom_bar(stat = "identity", width = 0.6, show.legend = FALSE) +
  geom_text(aes(label = n), vjust = 0, size = 4) +
  labs(title = "Jumlah Lowongan berdasarkan Status Gaji",
       x = "Status Gaji",
       y = "Jumlah Lowongan") +
  theme_minimal()

print(plot_gaji_bar)

Distribusi posisi gaji yang tidak diumumkan

library(dplyr)
library(ggplot2)
library(scales)

# 1. Filter data gaji tidak diumumkan dan hitung posisi
gaji_tidak_diumumkan <- data_kalibrr_cleaned %>%
  filter(is.na(Gaji_Numerik), !is.na(Posisi), Posisi != "") %>%
  count(Posisi, sort = TRUE) %>%
  top_n(10, n) %>%
  mutate(
    proporsi = n / sum(n),  # Hitung proporsi
    label = paste0(Posisi, " (", percent(proporsi), ")")  # Label gabungan
  )

# 2. Buat pie chart dengan persentase
plot_pie <- ggplot(gaji_tidak_diumumkan, aes(x = "", y = n, fill = Posisi)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y") +
  labs(title = "Distribusi Posisi dengan Gaji Tidak Diumumkan") +
  theme_void() +
  theme(legend.position = "right") +
  guides(fill = guide_legend(title = "Posisi")) +
  geom_text(aes(label = percent(proporsi)),
            position = position_stack(vjust = 0.5),
            size = 4, color = "white")

# 3. Tampilkan plot
print(plot_pie)

Boxplot sebaran gaji

# Visualisasi 2: Distribusi Gaji (setelah cleaning)
# Menggunakan Gaji_Numerik yang sudah bersih

if (!all(is.na(data_kalibrr_cleaned$Gaji_Numerik))) {
  
  
  # Box Plot (untuk melihat sebaran, median, kuartil, dan outlier)
  plot_boxplot_gaji <- ggplot(data_kalibrr_cleaned %>% filter(!is.na(Gaji_Numerik)), aes(y = Gaji_Numerik)) +
    geom_boxplot(fill = "#08306b", color = "black", alpha = 0.7) +
    scale_y_continuous(labels = scales::comma_format(big.mark = ".", decimal.mark = ",")) +
    labs(title = "Box Plot Sebaran Gaji",
         y = "Gaji (Rp)") +
    coord_flip() + # Membuat boxplot horizontal
    theme_minimal()
  print(plot_boxplot_gaji)
} else {
  print("Tidak ada data gaji numerik yang valid untuk divisualisasikan.")
}

Rata-rata gaji minimum per tingkat posisi

# Visualisasi 3: Rata-rata Gaji per Tingkat Posisi
# Sesuaikan "Tingkat Posisi" jika nama kolomnya berbeda.
TARGET_COL_TINGKAT_POSISI <- "Posisi" # Ganti jika nama kolom di file Anda berbeda

if (TARGET_COL_TINGKAT_POSISI %in% colnames(data_kalibrr_cleaned) && !all(is.na(data_kalibrr_cleaned$Gaji_Numerik))) {
  rata_gaji_per_tingkat <- data_kalibrr_cleaned %>%
    filter(!is.na(Gaji_Numerik) & !is.na(.data[[TARGET_COL_TINGKAT_POSISI]])) %>%
    group_by(.data[[TARGET_COL_TINGKAT_POSISI]]) %>%
    summarise(Rata_Rata_Gaji = mean(Gaji_Numerik, na.rm = TRUE),
              Jumlah_Lowongan = n()) %>%
    filter(Jumlah_Lowongan > 0) %>% # Hanya tampilkan yang ada data
    arrange(desc(Rata_Rata_Gaji))
  
  plot_gaji_tingkat_posisi <- ggplot(rata_gaji_per_tingkat, aes(x = reorder(.data[[TARGET_COL_TINGKAT_POSISI]], Rata_Rata_Gaji), y = Rata_Rata_Gaji, fill = .data[[TARGET_COL_TINGKAT_POSISI]])) +
    geom_bar(stat = "identity", show.legend = FALSE) +
    geom_text(aes(label = paste0("Rp ", scales::comma(Rata_Rata_Gaji, big.mark = ".", decimal.mark = ","))), 
          vjust = 0.5, hjust = 1.2, size = 3)+
    coord_flip() +
    scale_y_continuous(labels = scales::comma_format(prefix = "Rp ", big.mark = ".", decimal.mark = ",")) +
    labs(title = "Rata-rata Gaji per Tingkat Posisi",
         x = "Posisi",
         y = "Rata-rata Gaji (Rp)") +
    theme_minimal()
  print(plot_gaji_tingkat_posisi)
} else {
  print(paste("Kolom '", TARGET_COL_TINGKAT_POSISI, "' atau data gaji numerik tidak memadai untuk visualisasi ini.", sep=""))
}

if ("Status" %in% colnames(data_kalibrr_cleaned) & "Pekerjaan" %in% colnames(data_kalibrr_cleaned)) {
  # Ambil daftar pekerjaan dengan status kontrak
  pekerjaan_kontrak <- data_kalibrr_cleaned %>%
    filter(str_detect(Status, regex("kontrak", ignore_case = TRUE)), !is.na(Pekerjaan)) %>%
    count(Pekerjaan, sort = TRUE)

  # Menampilkan dataframe pekerjaan kontrak
  print(pekerjaan_kontrak)
} else {
  print("Kolom 'Status' atau 'Pekerjaan' tidak ditemukan. Periksa data dan pastikan kolom tersedia.")
}
##                                                  Pekerjaan n
## 1                             Springboot Backend Developer 9
## 2  Agency Relation Executive ARE Car Product Branch Tambun 3
## 3                                   Database Administrator 3
## 4            Developer Support Engineer  6 Months Contract 3
## 5                                      Fullstack Developer 3
## 6       Marketing Showroom Account Executive Branch Bekasi 3
## 7                   Medical Doctor Sales Manager Alomedika 3
## 8                           Microsoft Solutions Specialist 3
## 9                             Recovery Officer Area Bekasi 3
## 10                            Videographer & Editor Intern 3
# Pastikan nama kolom sesuai
if (all(c("Nama Perusahaan", "Posisi") %in% colnames(data_kalibrr_cleaned))) {
  
  # 1. Ambil perusahaan dengan jumlah lowongan terbanyak (Top 1)
  top1_perusahaan <- data_kalibrr_cleaned %>%
    filter(!is.na(`Nama Perusahaan`)) %>%
    count(`Nama Perusahaan`, sort = TRUE) %>%
    slice(1) %>%
    pull(`Nama Perusahaan`)
  
  # 2. Filter data berdasarkan perusahaan tersebut
  data_top1_posisi <- data_kalibrr_cleaned %>%
    filter(`Nama Perusahaan` == top1_perusahaan)
  
  # 3. Visualisasi posisi-posisi yang ditawarkan perusahaan tersebut
  plot_posisi_top1 <- data_top1_posisi %>%
    count(Posisi, sort = TRUE) %>%
    ggplot(aes(x = reorder(Posisi, n), y = n, fill = Posisi)) +
    geom_bar(stat = "identity", show.legend = FALSE) +
    geom_text(aes(label = n), hjust = 0, size = 3.5) +
    coord_flip() +
    labs(title = paste("Distribusi Posisi di", top1_perusahaan),
         x = "Posisi",
         y = "Jumlah Lowongan") +
    theme_minimal()
  
  print(plot_posisi_top1)
  
} else {
  print("Kolom 'Nama Perusahaan' atau 'Posisi' tidak ditemukan. Periksa nama kolom.")
}

# Pastikan nama kolom sesuai
if (all(c("Nama Perusahaan", "Posisi") %in% colnames(data_kalibrr_cleaned))) {
  
  # 1. Ambil perusahaan dengan jumlah lowongan terbanyak (Top 1)
  top1_perusahaan <- data_kalibrr_cleaned %>%
    filter(!is.na(`Nama Perusahaan`)) %>%
    count(`Nama Perusahaan`, sort = TRUE) %>%
    slice(2) %>%
    pull(`Nama Perusahaan`)
  
  # 2. Filter data berdasarkan perusahaan tersebut
  data_top1_posisi <- data_kalibrr_cleaned %>%
    filter(`Nama Perusahaan` == top1_perusahaan)
  
  # 3. Visualisasi posisi-posisi yang ditawarkan perusahaan tersebut
  plot_posisi_top1 <- data_top1_posisi %>%
    count(Posisi, sort = TRUE) %>%
    ggplot(aes(x = reorder(Posisi, n), y = n, fill = Posisi)) +
    geom_bar(stat = "identity", show.legend = FALSE) +
    geom_text(aes(label = n), hjust = 0, size = 3.5) +
    coord_flip() +
    labs(title = paste("Distribusi Posisi di", top1_perusahaan),
         x = "Posisi",
         y = "Jumlah Lowongan") +
    theme_minimal()
  
  print(plot_posisi_top1)
  
} else {
  print("Kolom 'Nama Perusahaan' atau 'Posisi' tidak ditemukan. Periksa nama kolom.")
}

# Install jika belum ada
#install.packages("wordcloud")
#install.packages("RColorBrewer")

# Panggil library
library(wordcloud)
## Warning: package 'wordcloud' was built under R version 4.4.3
## Loading required package: RColorBrewer
library(RColorBrewer)
library(dplyr)

frekuensi_pekerjaan <- data_kalibrr_cleaned %>%
  filter(!is.na(Pekerjaan)) %>%
  mutate(Pekerjaan = word(Pekerjaan, 1, 2)) %>%
  count(Pekerjaan) %>%
  arrange(desc(n))

# Buat wordcloud
wordcloud(words = frekuensi_pekerjaan$Pekerjaan,
          freq = frekuensi_pekerjaan$n,
          min.freq = 1,
          max.words = 100,
          random.order = FALSE,
          rot.per = 0.25,
          colors = brewer.pal(8, "Dark2"))
## Warning in wordcloud(words = frekuensi_pekerjaan$Pekerjaan, freq =
## frekuensi_pekerjaan$n, : Store Superintendent could not be fit on page. It will
## not be plotted.

data_kalibrr_cleaned %>%
  distinct(`Kota`) %>%
  count()  # atau: nrow( . )
##    n
## 1 41
library(dplyr)

data_kalibrr_cleaned %>%
  filter(Posisi == "Magang / OJT") %>%         # Filter berdasarkan status Magang
  distinct(`Nama Perusahaan`) %>%        # Ambil nama perusahaan unik
  arrange(`Nama Perusahaan`)             # Urutkan secara alfabetis
##                Nama Perusahaan
## 1              Kompas Gramedia
## 2 PT BFI Finance Indonesia Tbk
## 3                     Renos.id
library(dplyr)
library(ggplot2)

# Filter data untuk posisi Magang
magang_perusahaan <- data_kalibrr_cleaned %>%
  filter(Posisi == "Magang / OJT") %>%
  count(`Nama Perusahaan`, sort = TRUE) %>%
  top_n(10, n)  # Ambil 10 perusahaan teratas

# Visualisasi
ggplot(magang_perusahaan,
       aes(x = reorder(`Nama Perusahaan`, n), y = n, fill = `Nama Perusahaan`)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = n), hjust = -0.2) +
  coord_flip() +
  labs(title = "Perusahaan dengan Lowongan Magang",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan Magang") +
  theme_minimal()

library(dplyr)
library(ggplot2)

# Filter data Magang dan hitung jumlah per perusahaan
magang_perusahaan <- data_kalibrr_cleaned %>%
  filter(Posisi == "Magang / OJT") %>%
  count(`Nama Perusahaan`, sort = TRUE)

# Hitung proporsi
magang_perusahaan <- magang_perusahaan %>%
  mutate(prop = n / sum(n),
         label = paste0(`Nama Perusahaan`, " (", round(prop * 100, 1), "%)"))

# Donut chart
ggplot(magang_perusahaan, aes(x = 2, y = prop, fill = `Nama Perusahaan`)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar("y", start = 0) +
  geom_text(aes(label = ifelse(prop > 0.03, label, "")), 
            position = position_stack(vjust = 0.5), size = 3) +
  xlim(0.5, 2.5) +  # Membuat bagian tengah kosong (donut)
  labs(title = "Distribusi Lowongan Magang per Perusahaan") +
  theme_void() +
  theme(legend.position = "none")

library(dplyr)
library(ggplot2)

# Ambil 10 perusahaan teratas dengan lowongan Magang
top10_magang_perusahaan <- data_kalibrr_cleaned %>%
  filter(Posisi == "Magang / OJT") %>%
  count(`Nama Perusahaan`, sort = TRUE) %>%
  top_n(10, n) %>%
  pull(`Nama Perusahaan`)

# Ambil pekerjaan magang di perusahaan tersebut
magang_pekerjaan_perusahaan <- data_kalibrr_cleaned %>%
  filter(Posisi == "Magang / OJT", `Nama Perusahaan` %in% top10_magang_perusahaan) %>%
  count(`Nama Perusahaan`, Pekerjaan, sort = TRUE)

# Visualisasi: Stacked barplot
ggplot(magang_pekerjaan_perusahaan,
       aes(x = reorder(`Nama Perusahaan`, n, sum),
           y = n,
           fill = Pekerjaan)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  labs(title = "Lowongan Magang Berdasarkan Pekerjaan di 10 Perusahaan Teratas",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan",
       fill = "Pekerjaan") +
  theme_minimal()

library(dplyr)
library(ggplot2)

# Ambil 10 perusahaan teratas dengan lowongan Magang
top10_magang_perusahaan <- data_kalibrr_cleaned %>%
  filter(Posisi == "Supervisor / Asisten Manager") %>%
  count(`Nama Perusahaan`, sort = TRUE) %>%
  top_n(30, n) %>%
  pull(`Nama Perusahaan`)

# Ambil pekerjaan magang di perusahaan tersebut
magang_pekerjaan_perusahaan <- data_kalibrr_cleaned %>%
  filter(Posisi == "Supervisor / Asisten Manager", `Nama Perusahaan` %in% top10_magang_perusahaan) %>%
  count(`Nama Perusahaan`, Pekerjaan, sort = TRUE)

# Visualisasi: Stacked barplot
ggplot(magang_pekerjaan_perusahaan,
       aes(x = reorder(`Nama Perusahaan`, n, sum),
           y = n,
           fill = Pekerjaan)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  labs(title = "Lowongan Magang Berdasarkan Pekerjaan di 10 Perusahaan Teratas",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan",
       fill = "Pekerjaan") +
  theme_minimal()

library(dplyr)

data_kota_status <- data_kalibrr_cleaned %>%
  count(Kota, Status, name = "jumlah_lowongan")
library(dplyr)
library(ggplot2)

# Filter data untuk bulan Februari, September, dan Oktober
bulan_pilihan <- c("Februari", "September", "Oktober")

top_per_bulan <- data_kalibrr_cleaned %>%
  filter(Bulan %in% bulan_pilihan) %>%
  count(Bulan, `Nama Perusahaan`, sort = TRUE) %>%
  group_by(Bulan) %>%
  slice_max(n, n = 5) %>%
  ungroup()

# Visualisasi vertikal dengan facet wrap
ggplot(top_per_bulan, aes(x = reorder(`Nama Perusahaan`, n), y = n, fill = `Nama Perusahaan`)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = n), vjust = -0.3, size = 3) +
  labs(title = "Top 5 Perusahaan per Bulan (Februari, September, Oktober)",
       x = "Nama Perusahaan",
       y = "Jumlah Lowongan") +
  facet_wrap(~Bulan, scales = "free_x") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

library(dplyr)
library(ggplot2)
library(forcats)

# Susun urutan nama bulan
bulan_order <- c("Januari", "Februari", "Maret", "April", "Mei", "Juni",
                 "Juli", "Agustus", "September", "Oktober", "November", "Desember")

# Hitung jumlah perusahaan unik per bulan
data_perusahaan_bulanan <- data_kalibrr_cleaned %>%
  filter(!is.na(`Nama Perusahaan`), !is.na(Bulan)) %>%
  group_by(Bulan) %>%
  summarise(jumlah_perusahaan = n_distinct(`Nama Perusahaan`)) %>%
  ungroup() %>%
  mutate(Bulan = factor(Bulan, levels = bulan_order))

# Visualisasi jumlah perusahaan per bulan
ggplot(data_perusahaan_bulanan, aes(x = Bulan, y = jumlah_perusahaan, fill = Bulan)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = jumlah_perusahaan), vjust = -0.5) +
  labs(title = "Jumlah Perusahaan yang Membuka Lowongan per Bulan",
       x = "Bulan",
       y = "Jumlah Perusahaan") +
  theme_minimal()

library(dplyr)
library(ggplot2)
library(tidyr)
library(forcats)

# Pastikan format bulan
bulan_order <- c("Januari", "Februari", "Maret", "April", "Mei", "Juni",
                 "Juli", "Agustus", "September", "Oktober", "November", "Desember")

# Hitung jumlah lowongan dan jumlah perusahaan per bulan
data_summary <- data_kalibrr_cleaned %>%
  group_by(Bulan) %>%
  summarise(
    jumlah_lowongan = n(),
    jumlah_perusahaan = n_distinct(`Nama Perusahaan`)
  ) %>%
  mutate(Bulan = factor(Bulan, levels = bulan_order)) %>%
  arrange(Bulan)

# Ubah data ke format long untuk ggplot
data_long <- data_summary %>%
  pivot_longer(cols = c(jumlah_lowongan, jumlah_perusahaan),
               names_to = "Tipe",
               values_to = "Jumlah")

# Visualisasi Line Chart
ggplot(data_long, aes(x = Bulan, y = Jumlah, color = Tipe, group = Tipe)) +
  geom_line(size = 1.2) +
  geom_point(size = 2) +
  labs(title = "Jumlah Lowongan vs Perusahaan per Bulan",
       x = "Bulan",
       y = "Jumlah",
       color = "Jenis") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

# Korelasi antara Jumlah lowongan dan jumlah perusahaan
cor(data_summary$jumlah_lowongan, data_summary$jumlah_perusahaan, method = "pearson")
## [1] 0.9052499