1 Pendahuluan

Dataset yang digunakan adalah Movies Dataset yang bersumber dari Kaggle - Movies Industry Dataset. Dataset ini memuat informasi 7.668 film dari berbagai genre, tahun rilis, rating, anggaran, dan pendapatan kotor.

Variabel Kategorik:

Variabel Numerik:


2 Load Library dan Data

library(ggplot2)
library(dplyr)
library(readxl)
library(scales)
library(gridExtra)
library(RColorBrewer)
library(DT)

# Load data
df <- read_excel("movies.xlsx")

# Seleksi variabel yang digunakan
df <- df %>%
  select(name, country, year, rating, genre, score, runtime) %>%
  filter(!is.na(rating), !is.na(genre), !is.na(score), !is.na(runtime))

# Tampilkan seluruh dataset
DT::datatable(df, options = list(pageLength = 15, scrollX = TRUE), caption = "Dataset: Movies Industry")

3 Statistik Deskriptif

3.1 Variabel Numerik: Score (IMDb)

score_stats <- df %>%
  summarise(
    Mean     = mean(score, na.rm = TRUE),
    Median   = median(score, na.rm = TRUE),
    Modus    = as.numeric(names(sort(table(round(score, 1)), decreasing = TRUE)[1])),
    Q1       = quantile(score, 0.25, na.rm = TRUE),
    Q3       = quantile(score, 0.75, na.rm = TRUE),
    Range    = max(score, na.rm = TRUE) - min(score, na.rm = TRUE),
    Varians  = var(score, na.rm = TRUE),
    Std_Dev  = sd(score, na.rm = TRUE)
  )

knitr::kable(score_stats, digits = 4, caption = "Statistik Deskriptif: Score IMDb")
Statistik Deskriptif: Score IMDb
Mean Median Modus Q1 Q3 Range Varians Std_Dev
6.3884 6.5 6.6 5.8 7.1 7.4 0.9379 0.9685

3.2 Variabel Numerik: Runtime (Durasi)

runtime_stats <- df %>%
  summarise(
    Mean     = mean(runtime, na.rm = TRUE),
    Median   = median(runtime, na.rm = TRUE),
    Modus    = as.numeric(names(sort(table(runtime), decreasing = TRUE)[1])),
    Q1       = quantile(runtime, 0.25, na.rm = TRUE),
    Q3       = quantile(runtime, 0.75, na.rm = TRUE),
    Range    = max(runtime, na.rm = TRUE) - min(runtime, na.rm = TRUE),
    Varians  = var(runtime, na.rm = TRUE),
    Std_Dev  = sd(runtime, na.rm = TRUE)
  )

knitr::kable(runtime_stats, digits = 4, caption = "Statistik Deskriptif: Runtime (Menit)")
Statistik Deskriptif: Runtime (Menit)
Mean Median Modus Q1 Q3 Range Varians Std_Dev
107.2713 104 97 95 116 303 345.2565 18.5811

4 Visualisasi Data

4.1 1. Pie Chart — Proporsi Rating Film

library(gridExtra)
library(grid)

rating_all <- read_excel("movies.xlsx") %>%
  select(rating) %>%
  filter(!is.na(rating)) %>%
  count(rating, sort = TRUE) %>%
  mutate(pct = n / sum(n))

# Warna konsisten — urutan sesuai rating_all (sudah sort by n)
n_ratings <- nrow(rating_all)
colors    <- RColorBrewer::brewer.pal(max(n_ratings, 3), "Set3")[1:n_ratings]
names(colors) <- rating_all$rating   # ikat nama warna ke rating

pie_plot <- ggplot(rating_all, aes(x = "", y = pct, fill = rating)) +
  geom_col(width = 1, color = "white", linewidth = 0.5) +
  coord_polar(theta = "y") +
  scale_fill_manual(values = colors) +    # tanpa geom_text → tidak ada huruf di dalam
  labs(
    title   = "Pie Chart: Proporsi Rating Film",
    caption = "Sumber: Movies Industry Dataset (Kaggle)"
  ) +
  theme_void() +
  theme(
    plot.title      = element_text(hjust = 0.5, face = "bold", size = 14),
    legend.position = "none"
  )

# Tabel legend: warna kolom Rating = warna slice pie masing-masing
legend_df <- rating_all %>%
  mutate(
    Persentase = percent(pct, accuracy = 0.1),
    Jumlah     = formatC(n, format = "d", big.mark = ",")
  ) %>%
  select(Rating = rating, Persentase, Jumlah)

# Warna per baris (kolom Rating) sesuai urutan rating_all
row_fill <- colors[rating_all$rating]   # warna tepat per rating

legend_grob <- tableGrob(
  legend_df,
  rows  = NULL,
  theme = ttheme_minimal(
    core = list(
      fg_params = list(fontsize = 10),
      bg_params = list(
        # kolom 1 (Rating) pakai warna slice, kolom 2-3 putih
        fill = matrix(
          c(row_fill, rep("white", n_ratings), rep("white", n_ratings)),
          nrow = n_ratings, ncol = 3
        ),
        alpha = matrix(
          c(rep(0.55, n_ratings), rep(0, n_ratings), rep(0, n_ratings)),
          nrow = n_ratings, ncol = 3
        )
      )
    ),
    colhead = list(fg_params = list(fontsize = 11, fontface = "bold"))
  )
)

grid.arrange(pie_plot, legend_grob, ncol = 2, widths = c(2.8, 1.4))

Interpretasi:

  • Deskriptif: Rating R mendominasi dengan proporsi hampir 49% dari seluruh film, jauh lebih besar dibanding rating lainnya. Rating PG-13 dan PG menempati posisi kedua dan ketiga, sementara rating seperti G, Not Rated, dan NC-17 memiliki porsi yang sangat kecil.
  • Inferensial: Dominasi rating R mencerminkan bahwa industri film lebih banyak memproduksi konten untuk penonton dewasa. Distribusi yang tidak merata ini menunjukkan adanya pola pasar yang jelas, di mana film dewasa (R) memiliki segmen penonton paling besar dan menguntungkan secara komersial.

4.2 2. Bar Chart — Jumlah Film per Genre

genre_top <- df %>%
  count(genre, sort = TRUE) %>%
  top_n(10, n)

ggplot(genre_top, aes(x = reorder(genre, n), y = n, fill = genre)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  geom_text(aes(label = n), hjust = -0.2, size = 3.5) +
  coord_flip() +
  scale_fill_brewer(palette = "Paired") +
  labs(
    title   = "Bar Chart: Jumlah Film per Genre (Top 10)",
    x       = "Genre",
    y       = "Jumlah Film",
    caption = "Sumber: Movies Industry Dataset (Kaggle)"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    axis.text  = element_text(size = 11)
  ) +
  ylim(0, max(genre_top$n) * 1.1)

Interpretasi:

  • Deskriptif: Genre Comedy memiliki jumlah film terbanyak, diikuti Action dan Drama. Ketiga genre ini mendominasi industri film dengan selisih yang cukup jauh dibanding genre lainnya seperti Crime, Biography, dan Horror.
  • Inferensial: Tingginya produksi film Comedy dan Action mencerminkan preferensi pasar yang kuat terhadap hiburan ringan dan aksi. Produser cenderung mengikuti tren yang sudah terbukti menguntungkan, sehingga genre populer terus mendominasi dari tahun ke tahun.

4.3 3. Histogram — Distribusi Score IMDb

ggplot(df, aes(x = score)) +
  geom_histogram(binwidth = 0.2, fill = "#2196F3", color = "white", alpha = 0.85) +
  geom_vline(aes(xintercept = mean(score)), color = "red",    linetype = "dashed", linewidth = 1) +
  geom_vline(aes(xintercept = median(score)), color = "green", linetype = "dashed", linewidth = 1) +
  annotate("text", x = mean(df$score) + 0.15, y = 600, label = paste("Mean =", round(mean(df$score), 2)), color = "red",   size = 3.5) +
  annotate("text", x = median(df$score) - 0.15, y = 550, label = paste("Median =", round(median(df$score), 2)), color = "darkgreen", size = 3.5, hjust = 1) +
  labs(
    title   = "Histogram: Distribusi Score IMDb Film",
    x       = "Score IMDb",
    y       = "Frekuensi",
    caption = "Sumber: Movies Industry Dataset (Kaggle)"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(face = "bold", size = 14, hjust = 0.5))

Interpretasi:

  • Deskriptif: Distribusi score IMDb mendekati normal dengan mean ≈ 6.39 dan median ≈ 6.50. Sebagian besar film terkonsentrasi di rentang skor 5.5–7.5, dan terdapat lebih sedikit film dengan skor sangat rendah (<4) maupun sangat tinggi (>8.5).
  • Inferensial: Rata-rata skor film secara statistik berada di bawah 7.0, menunjukkan bahwa mayoritas film yang diproduksi dinilai penonton sebagai “cukup baik” namun belum mencapai kualitas unggulan. Hal ini dapat dikaitkan dengan tingginya volume produksi film yang tidak selalu diimbangi kualitas.

4.4 4. Histogram — Distribusi Runtime Film

ggplot(df, aes(x = runtime)) +
  geom_histogram(binwidth = 5, fill = "#FF9800", color = "white", alpha = 0.85) +
  geom_vline(aes(xintercept = mean(runtime)), color = "red",   linetype = "dashed", linewidth = 1) +
  geom_vline(aes(xintercept = median(runtime)), color = "blue", linetype = "dashed", linewidth = 1) +
  annotate("text", x = mean(df$runtime) + 8, y = 900, label = paste("Mean =", round(mean(df$runtime), 1)), color = "red",  size = 3.5) +
  annotate("text", x = median(df$runtime) - 8, y = 820, label = paste("Median =", round(median(df$runtime), 1)), color = "blue", size = 3.5, hjust = 1) +
  labs(
    title   = "Histogram: Distribusi Durasi Film (Runtime)",
    x       = "Runtime (Menit)",
    y       = "Frekuensi",
    caption = "Sumber: Movies Industry Dataset (Kaggle)"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(face = "bold", size = 14, hjust = 0.5))

Interpretasi:

  • Deskriptif: Distribusi durasi film condong ke kanan (right-skewed) dengan mayoritas film berdurasi 85–120 menit. Mean ≈ 107 menit sedikit lebih tinggi dari median ≈ 104 menit, menunjukkan adanya sejumlah film berdurasi sangat panjang yang menarik nilai rata-rata ke atas.
  • Inferensial: Durasi film yang terkonsentrasi di sekitar 90–110 menit mencerminkan standar industri yang sudah terbentuk, di mana produser menyesuaikan durasi agar sesuai dengan kapasitas perhatian penonton di bioskop. Film yang terlalu pendek atau terlalu panjang cenderung lebih jarang diproduksi.

4.5 5. Density Plot — Distribusi Score IMDb

ggplot(df, aes(x = score)) +
  geom_density(fill = "#9C27B0", alpha = 0.5, color = "#6A1B9A", linewidth = 1) +
  geom_vline(aes(xintercept = mean(score)),   color = "red",   linetype = "dashed", linewidth = 1) +
  geom_vline(aes(xintercept = median(score)), color = "blue",  linetype = "dashed", linewidth = 1) +
  labs(
    title    = "Density Plot: Distribusi Score IMDb Film",
    subtitle = "Garis merah = Mean | Garis biru = Median",
    x        = "Score IMDb",
    y        = "Densitas",
    caption  = "Sumber: Movies Industry Dataset (Kaggle)"
  ) +
  theme_minimal() +
  theme(
    plot.title    = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(hjust = 0.5, size = 10)
  )

Interpretasi:

  • Deskriptif: Kurva density menunjukkan distribusi score yang hampir simetris dengan puncak di sekitar 6.5–7.0. Kurva yang relatif sempit (SD ≈ 0.97) mengindikasikan bahwa penilaian penonton terhadap film cukup konsisten dan tidak terlalu bervariasi.
  • Inferensial: Bentuk distribusi yang mendekati normal mendukung penggunaan metode statistik parametrik untuk analisis lebih lanjut. Puncak distribusi yang berada di bawah 7.0 memperkuat temuan bahwa rata-rata kualitas film secara keseluruhan masih berada pada level “cukup” menurut penilaian penonton IMDb.

4.6 6. Boxplot — Distribusi Score per Rating

ggplot(df, aes(x = reorder(rating, score, median), y = score, fill = rating)) +
  geom_boxplot(alpha = 0.7, outlier.color = "red", outlier.size = 1.5) +
  scale_fill_brewer(palette = "Set3") +
  labs(
    title   = "Boxplot: Distribusi Score IMDb berdasarkan Rating",
    x       = "Rating",
    y       = "Score IMDb",
    fill    = "Rating",
    caption = "Sumber: Movies Industry Dataset (Kaggle)"
  ) +
  theme_minimal() +
  theme(
    plot.title    = element_text(face = "bold", size = 14, hjust = 0.5),
    legend.position = "none"
  )

Interpretasi:

  • Deskriptif: Film dengan rating G memiliki median score tertinggi, sedangkan film rating R memiliki median score terendah di antara kelompok utama. Rating Not Rated menunjukkan IQR yang lebar, mengindikasikan variasi kualitas yang besar pada film tanpa klasifikasi resmi. Titik merah adalah outlier pada masing-masing kelompok rating.
  • Inferensial: Rating film berpengaruh terhadap skor yang diterima. Film rating G (umumnya film keluarga) cenderung mendapat penilaian lebih tinggi karena dibuat dengan standar kualitas yang lebih ketat dan menargetkan audiens yang lebih luas lintas usia.

4.7 7. Boxplot — Distribusi Runtime per Genre (Top 5)

top5_genre <- df %>%
  count(genre, sort = TRUE) %>%
  top_n(5, n) %>%
  pull(genre)

df_top5 <- df %>% filter(genre %in% top5_genre)

ggplot(df_top5, aes(x = reorder(genre, runtime, median), y = runtime, fill = genre)) +
  geom_boxplot(alpha = 0.7, outlier.color = "darkred", outlier.size = 1.5) +
  scale_fill_brewer(palette = "Pastel1") +
  labs(
    title   = "Boxplot: Distribusi Runtime berdasarkan Genre (Top 5)",
    x       = "Genre",
    y       = "Runtime (Menit)",
    fill    = "Genre",
    caption = "Sumber: Movies Industry Dataset (Kaggle)"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    legend.position = "none"
  )

Interpretasi:

  • Deskriptif: Film genre Drama memiliki median runtime tertinggi, sedangkan Comedy cenderung paling pendek. IQR yang lebar pada genre Action menunjukkan variasi durasi yang tinggi — ada film action yang singkat maupun sangat panjang. Genre Biography memiliki distribusi yang cukup sempit dan konsisten.
  • Inferensial: Genre film secara nyata mempengaruhi durasi yang dibutuhkan untuk menyampaikan cerita. Drama memerlukan waktu lebih panjang untuk membangun emosi dan karakter, sementara Comedy dirancang lebih ringkas agar ritme humor tetap terjaga dan tidak kehilangan daya tariknya.

5 Kesimpulan

Berdasarkan analisis data film:

  1. Genre paling banyak adalah Comedy, Action, dan Drama, dengan distribusi yang tidak seragam.
  2. Rating R mendominasi industri film sebesar ~48% dari total dataset.
  3. Score IMDb terdistribusi mendekati normal dengan rata-rata 6.39 (SD = 0.97), menunjukkan kualitas film yang cukup konsisten.
  4. Runtime film mayoritas berada di 90–120 menit, dengan film drama cenderung lebih panjang.
  5. Terdapat perbedaan signifikan score antar kelompok rating dan runtime antar genre berdasarkan uji statistik inferensia.

Dataset: Movies Industry — Kaggle | Analisis menggunakan R dan ggplot2