Agregasi dan Visualisasi Profil Perusahaan Tercatat

Project UAS MDS Kelompok 6:

M0501241031 Jefita Resti Sari

M0501241038 Sely Fitriatun

M0501241048 Claudian Tikulimbong Tangdiloban

M0501241063 Baiq Nina Febriati

Koneksi Data MongoDB

library(mongolite)
Warning: package 'mongolite' was built under R version 4.4.3
# KONEKSI
conn <- mongo(
  collection = "Profil Perusahaan Tercatat",
  db = "mds",
  url = "mongodb+srv://jefitaa:Jefitars02!@cluster0.jbglyd0.mongodb.net/")

Agregasi Data Profil Perusahaan Tercatat

Pemilik Saham 1

query_pemilik <- '[
  {
    "$group": {
      "_id": "$Pemilik Saham 1",
      "jumlah_perusahaan": { "$sum": 1 }
    }
  },
  {
    "$sort": { "jumlah_perusahaan": -1 }
  }
]'

hasil_pemilik <- conn$aggregate(query_pemilik)
print(head(hasil_pemilik))
                               _id jumlah_perusahaan
1            Masyarakat Non Warkat               120
2                             <NA>                55
3                       Masyarakat                27
4    PT Biro Klasifikasi Indonesia                 4
5 PT Semen Indonesia (Persero) Tbk                 2
6            PT Barito Pacific Tbk                 2

Jumlah Emiten per Corporate Secretary

agg_corpsec <- conn$aggregate('[
  {
    "$group": {
      "_id": "$Corporate Secretary",
      "jumlah_emiten": { "$sum": 1 }
    }
  },
  {
    "$sort": { "jumlah_emiten": -1 }
  }
]')

print(head(agg_corpsec))
                       _id jumlah_emiten
1         Yudhi Surjadjaja             2
2         Satrio Boediarto             1
3         Agianita Julinda             1
4    Febrina Kenya Savitri             1
5 Chadafy Maraden Sibarani             1
6             Asep Mulyana             1

Jumlah Emiten berdasarkan Tahun IPO (Listing Date)

agg_tahun_listing <- conn$aggregate('[
  {
    "$project": {
      "tahun": { "$substr": [ "$Listing Date", 6, 4 ] }
    }
  },
  {
    "$group": {
      "_id": "$tahun",
      "jumlah_emiten": { "$sum": 1 }
    }
  },
  {
    "$sort": { "_id": 1 }
  }
]')

print(agg_tahun_listing)
    _id jumlah_emiten
1                   1
2  1977             1
3  1979             1
4  1980             2
5  1981             2
6  1982             4
7  1983             2
8  1984             2
9  1989            24
10 1990            51
11 1991            12
12 1992            10
13 1993            12
14 1994            30
15 1995            15
16 1996            10
17 1997            22
18 1998             3
19 1999             4
20 2000            15
21 2001            22
22 2002            19
23 2003             8
24 2004            12
25 2005             8
26 2006            11
27 2007            21
28 2008            16
29 2009            11
30 2010            20
31 2011            25
32 2012            23
33 2013            28
34 2014            22
35 2015            17
36 2016            15
37 2017            36
38 2018            57
39 2019            55
40 2020            49
41 2021            54
42 2022            55
43 2023            75
44 2024            40
45 2025            13

Jumlah Emitmen berdasarkan Komisaris Utama

agg_komut <- conn$aggregate('[
  {
    "$group": {
      "_id": "$Komisaris Utama",
      "jumlah_emiten": { "$sum": 1 }
    }
  },
  {
    "$sort": { "jumlah_emiten": -1 }
  }
]')

print(head(agg_komut))
                    _id jumlah_emiten
1                  <NA>            16
2       Hermanto Tanoko             5
3     Edwin Soeryadjaya             5
4 Franky Oesman Widjaja             3
5        Muktar Widjaja             3
6         Fendi Santoso             2

Lokasi (Alamat)

query <- '[
  {
    "$addFields": {
      "kota": {
        "$switch": {
          "branches": [
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "banda aceh", "options": "i" } }, "then": "Banda Aceh" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "medan", "options": "i" } }, "then": "Medan" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "padang", "options": "i" } }, "then": "Padang" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "pekanbaru", "options": "i" } }, "then": "Pekanbaru" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "tanjung pinang", "options": "i" } }, "then": "Tanjung Pinang" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "jambi", "options": "i" } }, "then": "Jambi" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "bengkulu", "options": "i" } }, "then": "Bengkulu" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "palembang", "options": "i" } }, "then": "Palembang" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "pangkalpinang", "options": "i" } }, "then": "Pangkalpinang" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "bandar lampung", "options": "i" } }, "then": "Bandar Lampung" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "jakarta", "options": "i" } }, "then": "Jakarta" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "bandung", "options": "i" } }, "then": "Bandung" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "serang", "options": "i" } }, "then": "Serang" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "semarang", "options": "i" } }, "then": "Semarang" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "yogyakarta", "options": "i" } }, "then": "Yogyakarta" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "surabaya", "options": "i" } }, "then": "Surabaya" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "denpasar", "options": "i" } }, "then": "Denpasar" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "mataram", "options": "i" } }, "then": "Mataram" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "kupang", "options": "i" } }, "then": "Kupang" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "pontianak", "options": "i" } }, "then": "Pontianak" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "palangka raya", "options": "i" } }, "then": "Palangka Raya" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "banjarmasin", "options": "i" } }, "then": "Banjarmasin" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "samarinda", "options": "i" } }, "then": "Samarinda" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "tanjung selor", "options": "i" } }, "then": "Tanjung Selor" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "manado", "options": "i" } }, "then": "Manado" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "palu", "options": "i" } }, "then": "Palu" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "makassar", "options": "i" } }, "then": "Makassar" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "kendari", "options": "i" } }, "then": "Kendari" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "gorontalo", "options": "i" } }, "then": "Gorontalo" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "mamuju", "options": "i" } }, "then": "Mamuju" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "ambon", "options": "i" } }, "then": "Ambon" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "sofifi", "options": "i" } }, "then": "Sofifi" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "jayapura", "options": "i" } }, "then": "Jayapura" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "manokwari", "options": "i" } }, "then": "Manokwari" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "wamena", "options": "i" } }, "then": "Wamena" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "merauke", "options": "i" } }, "then": "Merauke" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "nabire", "options": "i" } }, "then": "Nabire" },
            { "case": { "$regexMatch": { "input": "$Alamat", "regex": "sorong", "options": "i" } }, "then": "Sorong" }
          ],
          "default": "Lainnya"
        }
      }
    }
  },
  {
    "$group": {
      "_id": "$kota",
      "jumlah_perusahaan": { "$sum": 1 }
    }
  },
  {
    "$sort": { "jumlah_perusahaan": -1 }
  }
]'
hasil_agregasi <- conn$aggregate(query)
print(hasil_agregasi)
              _id jumlah_perusahaan
1         Jakarta               646
2         Lainnya               202
3        Surabaya                31
4           Medan                12
5         Bandung                10
6        Semarang                 9
7      Yogyakarta                 7
8          Serang                 7
9       Palembang                 4
10      Pekanbaru                 2
11       Denpasar                 1
12       Makassar                 1
13         Padang                 1
14      Samarinda                 1
15 Bandar Lampung                 1

Jumlah Perusahaan per Sektor

agg_sektor <- conn$aggregate('[
  {
    "$group": {
      "_id": "$Sektor", 
      "jumlah_perusahaan": { "$sum": 1 }
    }
  },
  {
    "$sort": { "jumlah_perusahaan": -1 }
  }
]')
print(agg_sektor)
  _id jumlah_perusahaan
1  NA               935

Direktur Utama

query_dirut <- '[
  {
    "$group": {
      "_id": "$Direktur Utama",
      "jumlah_perusahaan": { "$sum": 1 }
    }
  },
  {
    "$sort": { "jumlah_perusahaan": -1 }
  }
]'

hasil_dirut <- conn$aggregate(query_dirut)
print(head(hasil_dirut))
                 _id jumlah_perusahaan
1               <NA>                 8
2        Ardi Kusuma                 2
3 Hary Tanoesoedibjo                 2
4            Michael                 2
5            Firdaus                 2
6       Edward Halim                 2

Jumlah Jabatan (Komisaris + Direktur + Komite)

query_jumlah <- '[
  {
    "$project": {
      "Nama": 1,
      "jumlah_komisaris": {
        "$size": {
          "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "as": "item",
            "cond": { "$regexMatch": { "input": "$$item.k", "regex": "Komisaris", "options": "i" } }
          }
        }
      },
      "jumlah_direktur": {
        "$size": {
          "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "as": "item",
            "cond": { "$regexMatch": { "input": "$$item.k", "regex": "Direktur", 
"options": "i" } }
          }
        }
      },
      "jumlah_komite": {
        "$size": {
          "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "as": "item",
            "cond": { "$regexMatch": { "input": "$$item.k", "regex": "Komite",            
"options": "i" } }
          }
        }
      }
    }
  },
  {
    "$project": { "_id": 0 }
  }
]'

hasil_jumlah <- conn$aggregate(query_jumlah)
print(head(hasil_jumlah))
                             Nama jumlah_komisaris jumlah_direktur
1  PT Adaro Andalan Indonesia Tbk                2               4
2          Astra Agro Lestari Tbk                4               7
3                Mahaka Media Tbk                3               2
4     Asuransi Bina Dana Arta Tbk                4               4
5               ABM Investama Tbk                4               4
6 PT Aspirasi Hidup Indonesia Tbk                5               5
  jumlah_komite
1             3
2             3
3             3
4             3
5             3
6             3

Visualisasi Data

library(ggplot2)
library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(treemapify)
Warning: package 'treemapify' was built under R version 4.4.3
library(ggrepel)
#Top 7 Pemilik Saham dengan Jumlah Emiten Terbanyak

library(ggplot2)
library(dplyr)

# Jika hasil dari Mongo masih: "_id" dan "jumlah_perusahaan"
df <- hasil_pemilik %>%
  rename(Pemilik = `_id`, Jumlah = jumlah_perusahaan) %>%
  arrange(desc(Jumlah)) %>%
  slice(1:7)  # Tampilkan hanya 7 teratas

# Plot horizontal bar
ggplot(df, aes(x = Jumlah, y = reorder(Pemilik, Jumlah))) +
  geom_col(fill = "steelblue") +
  labs(
    title = "Top 7 Pemilik Saham dengan Jumlah Emiten Terbanyak",
    x = "Jumlah Emiten", y = "Pemilik Saham"
  ) +
  theme_minimal(base_size = 12) +
  theme(axis.text.y = element_text(size = 10))

#Jumlah Emiten berdasarkan Tahun IPO

library(ggplot2)
library(dplyr)

# Rename kolom agar lebih mudah digunakan
df_tahun <- agg_tahun_listing %>%
  rename(Tahun = `_id`, Jumlah = jumlah_emiten) %>%
  mutate(Tahun = as.numeric(Tahun))  # ubah ke numerik untuk sumbu X

# Line plot untuk tren emiten
ggplot(df_tahun, aes(x = Tahun, y = Jumlah)) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color = "darkblue", size = 2) +
  labs(title = "Tren Jumlah Emiten berdasarkan Tahun IPO",
       x = "Tahun", y = "Jumlah Emiten") +
  theme_minimal(base_size = 12)
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

#Top 10 Komisaris Utama dengan Emiten Terbanyak

library(dplyr)

df_komut <- agg_komut %>%
  rename(Komisaris = `_id`, Jumlah = jumlah_emiten) %>%
  mutate(Komisaris = ifelse(is.na(Komisaris) | Komisaris == "NA", "Tidak Diketahui", Komisaris)) %>%
  slice_max(order_by = Jumlah, n = 10, with_ties = FALSE)  # fix: ambil top 10 saja

ggplot(df_komut, aes(x = Jumlah, y = reorder(Komisaris, Jumlah))) +
  geom_col(fill = "darkorange") +
  labs(
    title = "Top 10 Komisaris Utama dengan Emiten Terbanyak",
    x = "Jumlah Emiten", y = "Komisaris Utama"
  ) +
  theme_minimal(base_size = 12)

library(ggplot2)
library(dplyr)

df_kota <- hasil_agregasi %>%
  rename(Kota = `_id`, Jumlah = jumlah_perusahaan) %>%
  arrange(desc(Jumlah))

ggplot(df_kota, aes(x = Jumlah, y = reorder(Kota, Jumlah))) +
  geom_col(fill = "green") +
  labs(
    title = "Jumlah Perusahaan per Kota",
    x = "Jumlah Perusahaan",
    y = "Kota"
  ) +
  theme_minimal(base_size = 12)

#Total Jabatan Setiap Perusahaan

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

# Data reshaping ke format long agar bisa plot bar side-by-side
df_long <- hasil_jumlah %>%
  pivot_longer(cols = c(jumlah_komisaris, jumlah_direktur, jumlah_komite),
               names_to = "Jabatan",
               values_to = "Jumlah")

# Ambil Top 10 perusahaan berdasarkan total jabatan (komisaris + direktur)
df_top10 <- df_long %>%
  group_by(Nama) %>%
  summarise(Total = sum(Jumlah)) %>%
  arrange(desc(Total)) %>%
  slice(1:10) %>%
  inner_join(df_long, by = "Nama") %>%
  mutate(Nama = factor(Nama, levels = unique(Nama)))

# Plot
ggplot(df_top10, aes(x = Nama, y = Jumlah, fill = Jabatan)) +
  geom_bar(stat = "identity", position = position_dodge()) +
  coord_flip() +
  labs(title = "Top 10 Jumlah Komisaris, Direktur dan Komite per Perusahaan",
       x = "Nama Perusahaan",
       y = "Jumlah") +
  scale_fill_manual(values = c("jumlah_komisaris" = "orange", "jumlah_direktur" = "steelblue", "jumlah_komite" = "maroon"),
                    labels = c("Komisaris", "Direktur", "Komite")) +
  theme_minimal(base_size = 12)

#Lokasi Perusahaan

library(dplyr)
library(tibble)

# Ambil data hasil agregasi Mongo
df_kota <- hasil_agregasi %>%
  rename(Kota = `_id`, Jumlah = jumlah_perusahaan)

# Tambahkan koordinat untuk lebih banyak kota
koordinat_kota <- tibble(
  Kota = c(
    "Jakarta", "Surabaya", "Bandung", "Medan", "Semarang",
    "Yogyakarta", "Serang", "Palembang", "Pekanbaru",
    "Makassar", "Samarinda", "Lainnya"
  ),
  lat = c(
    -6.2088, -7.2504, -6.9175, 3.5952, -6.9667,
    -7.8014, -6.1214, -2.9761, 0.5071,
    -5.1477, -0.5022, NA
  ),
  lon = c(
    106.8456, 112.7688, 107.6191, 98.6722, 110.4381,
    110.3647, 106.1572, 104.7754, 101.4478,
    119.4327, 117.1537, NA
  )
)

# Gabungkan koordinat ke data jumlah perusahaan
df_map <- left_join(df_kota, koordinat_kota, by = "Kota") %>%
  filter(!is.na(lat))

library(dplyr)
library(tibble)

# Ambil data hasil agregasi Mongo
df_kota <- hasil_agregasi %>%
  rename(Kota = `_id`, Jumlah = jumlah_perusahaan)

# Tambahkan koordinat untuk lebih banyak kota
koordinat_kota <- tibble(
  Kota = c(
    "Jakarta", "Surabaya", "Bandung", "Medan", "Semarang",
    "Yogyakarta", "Serang", "Palembang", "Pekanbaru",
    "Makassar", "Samarinda", "Lainnya"
  ),
  lat = c(
    -6.2088, -7.2504, -6.9175, 3.5952, -6.9667,
    -7.8014, -6.1214, -2.9761, 0.5071,
    -5.1477, -0.5022, NA
  ),
  lon = c(
    106.8456, 112.7688, 107.6191, 98.6722, 110.4381,
    110.3647, 106.1572, 104.7754, 101.4478,
    119.4327, 117.1537, NA
  )
)

# Gabungkan koordinat ke data jumlah perusahaan
df_map <- left_join(df_kota, koordinat_kota, by = "Kota") %>%
  filter(!is.na(lat))

library(leaflet)

library(leaflet)

# Buat palet warna unik berdasarkan nama kota
pal_kota <- colorFactor(palette = "Set1", domain = df_map$Kota)

leaflet(df_map) %>%
  addTiles() %>%
  addCircleMarkers(
    ~lon, ~lat,
    radius = ~sqrt(Jumlah),  # Ukuran berdasarkan jumlah perusahaan
    color = ~pal_kota(Kota), # Warna berdasarkan kota
    label = ~paste(Kota, ":", Jumlah, "perusahaan"),
    fillOpacity = 0.8, stroke = TRUE
  ) %>%
  addLegend("bottomright", pal = pal_kota, values = ~Kota,
            title = "Kota", opacity = 1)
Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set1 is 9
Returning the palette you asked for with that many colors
Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set1 is 9
Returning the palette you asked for with that many colors
Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set1 is 9
Returning the palette you asked for with that many colors