Kelompok 4 - Agni Tri Tania Siboro (3337250050) - Dina Wulandari (3337250144) - Findy Aprilia (3337250107) - Nayla Mesa Ayu (3337250145) - Putri Kaira Langi (3337250082)
Netflix merupakan salah satu platform streaming terbesar di dunia dengan jutaan pelanggan aktif. Platform ini menyediakan berbagai konten hiburan, mulai dari film layar lebar hingga serial TV dari berbagai genre dan negara.
Analisis ini menggunakan dataset Netflix Movies and TV Shows yang memuat informasi lengkap tentang konten yang tersedia di Netflix, seperti jenis konten, rating usia, tahun rilis, dan durasi. Dengan menggunakan metode Statistika Deskriptif, kita akan mengeksplorasi karakteristik data melalui ukuran pemusatan, penyebaran, serta berbagai visualisasi untuk memahami pola yang ada dalam dataset.
| Keterangan | Detail |
|---|---|
| Nama Dataset | Netflix Movies and TV Shows |
| Sumber | Kaggle - Shivamb |
| Jumlah Observasi | 8.807 judul |
| Jumlah Variabel | 12 variabel |
| Tipe Variabel | Nama Variabel | Keterangan |
|---|---|---|
| Kategorik | type |
Jenis konten: Movie atau TV Show |
| Kategorik | rating |
Rating usia (TV-MA, TV-14, PG-13, dll.) |
| Numerik | release_year |
Tahun rilis konten |
| Numerik | duration_minutes |
Durasi film dalam menit (khusus Movie) |
# Download file netflix_titles.csv dari:
# https://www.kaggle.com/datasets/shivamb/netflix-shows
# Simpan di folder yang sama dengan file .Rmd ini
netflix <- read.csv(
"netflix_titles.csv",
stringsAsFactors = FALSE,
na.strings = c("", "NA")
)
# Tampilkan dimensi dan preview data
cat("Dimensi data:", nrow(netflix), "baris x", ncol(netflix), "kolom\n")## Dimensi data: 8807 baris x 12 kolom
## type title rating release_year duration
## 1 Movie Dick Johnson Is Dead PG-13 2020 90 min
## 2 TV Show Blood & Water TV-MA 2021 2 Seasons
## 3 TV Show Ganglands TV-MA 2021 1 Season
## 4 TV Show Jailbirds New Orleans TV-MA 2021 1 Season
## 5 TV Show Kota Factory TV-MA 2021 2 Seasons
# Fungsi untuk menghitung modus
modus <- function(x) {
x <- x[!is.na(x)]
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
# Pembersihan dan transformasi
netflix_clean <- netflix %>%
filter(!is.na(type), !is.na(rating), !is.na(release_year)) %>%
mutate(
duration_value = as.numeric(gsub("[^0-9]", "", duration)),
duration_minutes = ifelse(type == "Movie", duration_value, NA),
rating_group = case_when(
rating %in% c("G", "TV-G", "TV-Y", "TV-Y7", "TV-Y7-FV") ~ "Anak-Anak",
rating %in% c("PG", "TV-PG", "PG-13", "TV-14") ~ "Remaja",
rating %in% c("R", "TV-MA", "NC-17", "NR", "UR") ~ "Dewasa",
TRUE ~ "Lainnya"
)
)
cat("Data siap dianalisis:", nrow(netflix_clean), "baris\n")## Data siap dianalisis: 8803 baris
type - Jenis Kontentabel_type <- netflix_clean %>%
count(type) %>%
mutate(Persentase = round(n / sum(n) * 100, 2)) %>%
rename(Kategori = type, Frekuensi = n)
kable(tabel_type, caption = "Tabel Frekuensi Jenis Konten Netflix") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "bordered"),
full_width = FALSE
)| Kategori | Frekuensi | Persentase |
|---|---|---|
| Movie | 6129 | 69.62 |
| TV Show | 2674 | 30.38 |
ggplot(tabel_type, aes(x = "", y = Frekuensi, fill = Kategori)) +
geom_bar(stat = "identity", width = 1, color = "white") +
coord_polar("y") +
geom_text(
aes(label = paste0(Persentase, "%")),
position = position_stack(vjust = 0.5),
color = "white", size = 6, fontface = "bold"
) +
scale_fill_manual(values = c("Movie" = "#E50914", "TV Show" = "#221F1F")) +
labs(title = "Proporsi Jenis Konten di Netflix", fill = "Jenis Konten") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"))Proporsi Jenis Konten di Netflix
Interpretasi: Konten Netflix didominasi oleh
Movie (~69%) dibandingkan TV Show (~31%). Modus
variabel type adalah “Movie”. Dominasi
film ini mencerminkan strategi Netflix yang lebih banyak menyediakan
konten film untuk menarik pelanggan baru.
rating - Rating Kontentabel_rating <- netflix_clean %>%
count(rating) %>%
arrange(desc(n)) %>%
mutate(Persentase = round(n / sum(n) * 100, 2)) %>%
rename(Rating = rating, Frekuensi = n)
kable(tabel_rating, caption = "Tabel Frekuensi Rating Konten Netflix") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "bordered"),
full_width = FALSE
)| Rating | Frekuensi | Persentase |
|---|---|---|
| TV-MA | 3207 | 36.43 |
| TV-14 | 2160 | 24.54 |
| TV-PG | 863 | 9.80 |
| R | 799 | 9.08 |
| PG-13 | 490 | 5.57 |
| TV-Y7 | 334 | 3.79 |
| TV-Y | 307 | 3.49 |
| PG | 287 | 3.26 |
| TV-G | 220 | 2.50 |
| NR | 80 | 0.91 |
| G | 41 | 0.47 |
| TV-Y7-FV | 6 | 0.07 |
| NC-17 | 3 | 0.03 |
| UR | 3 | 0.03 |
| 66 min | 1 | 0.01 |
| 74 min | 1 | 0.01 |
| 84 min | 1 | 0.01 |
netflix_clean %>%
count(rating) %>%
arrange(desc(n)) %>%
ggplot(aes(x = reorder(rating, n), y = n, fill = n)) +
geom_bar(stat = "identity", color = "white") +
geom_text(aes(label = n), hjust = -0.2, size = 3.5) +
coord_flip() +
scale_fill_gradient(low = "#ff9999", high = "#E50914") +
labs(
title = "Distribusi Rating Konten di Netflix",
x = "Rating",
y = "Jumlah Konten"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
legend.position = "none"
)Distribusi Rating Konten di Netflix
Interpretasi: Rating TV-MA (dewasa)
adalah yang paling dominan (~36%), diikuti oleh TV-14 dan TV-PG. Modus
variabel rating adalah “TV-MA”. Hal ini
menunjukkan bahwa Netflix menargetkan penonton dewasa sebagai segmen
pasar utamanya.
release_year - Tahun Rilisyear_data <- netflix_clean$release_year
stats_year <- data.frame(
Statistik = c("Mean", "Median", "Modus", "Q1 (Kuartil 1)", "Q3 (Kuartil 3)",
"Range", "Varians", "Standar Deviasi", "Minimum", "Maksimum"),
Nilai = c(
round(mean(year_data, na.rm = TRUE), 2),
median(year_data, na.rm = TRUE),
modus(year_data),
quantile(year_data, 0.25, na.rm = TRUE),
quantile(year_data, 0.75, na.rm = TRUE),
diff(range(year_data, na.rm = TRUE)),
round(var(year_data, na.rm = TRUE), 2),
round(sd(year_data, na.rm = TRUE), 2),
min(year_data, na.rm = TRUE),
max(year_data, na.rm = TRUE)
)
)
kable(stats_year, caption = "Statistik Deskriptif: Tahun Rilis") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "bordered"),
full_width = FALSE
)| Statistik | Nilai |
|---|---|
| Mean | 2014.18 |
| Median | 2017.00 |
| Modus | 2018.00 |
| Q1 (Kuartil 1) | 2013.00 |
| Q3 (Kuartil 3) | 2019.00 |
| Range | 96.00 |
| Varians | 77.81 |
| Standar Deviasi | 8.82 |
| Minimum | 1925.00 |
| Maksimum | 2021.00 |
ggplot(netflix_clean, aes(x = release_year)) +
geom_histogram(binwidth = 3, fill = "#E50914", color = "white", alpha = 0.85) +
geom_vline(xintercept = mean(year_data, na.rm = TRUE),
color = "blue", linetype = "dashed", linewidth = 1) +
geom_vline(xintercept = median(year_data, na.rm = TRUE),
color = "darkgreen", linetype = "solid", linewidth = 1) +
annotate("text",
x = mean(year_data, na.rm = TRUE) - 3, y = 700,
label = paste("Mean =", round(mean(year_data, na.rm = TRUE), 1)),
color = "blue", size = 3.5) +
annotate("text",
x = median(year_data, na.rm = TRUE) + 4, y = 600,
label = paste("Median =", median(year_data, na.rm = TRUE)),
color = "darkgreen", size = 3.5) +
labs(
title = "Histogram Tahun Rilis Konten Netflix",
x = "Tahun Rilis",
y = "Frekuensi"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"))Histogram Tahun Rilis Konten Netflix
Interpretasi: Distribusi tahun rilis bersifat miring ke kiri (negative skew), dengan konten terbanyak dirilis pada periode 2015-2021. Nilai Mean < Median mengkonfirmasi kemiringan ini, yang disebabkan oleh konten lama sebagai outlier. Tren ini mencerminkan pertumbuhan konten Netflix yang pesat dalam satu dekade terakhir.
ggplot(netflix_clean, aes(x = release_year, fill = type)) +
geom_density(alpha = 0.6) +
scale_fill_manual(values = c("Movie" = "#E50914", "TV Show" = "#221F1F")) +
labs(
title = "Density Plot Tahun Rilis Berdasarkan Jenis Konten",
x = "Tahun Rilis",
y = "Densitas",
fill = "Jenis Konten"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"))Density Plot Tahun Rilis Berdasarkan Jenis Konten
Interpretasi: Distribusi Movie dan TV Show memiliki pola yang serupa, dengan puncak di sekitar 2018-2020. TV Show memiliki ekor yang lebih panjang ke kiri, menandakan adanya serial TV yang lebih tua. Kedua jenis konten mengalami lonjakan produksi yang signifikan seiring meningkatnya popularitas layanan streaming.
duration_minutes - Durasi Filmmovie_data <- netflix_clean %>%
filter(type == "Movie", !is.na(duration_minutes))
cat("Jumlah data film:", nrow(movie_data), "\n")## Jumlah data film: 6126
dur_data <- movie_data$duration_minutes
stats_dur <- data.frame(
Statistik = c("Mean", "Median", "Modus", "Q1 (Kuartil 1)", "Q3 (Kuartil 3)",
"Range", "Varians", "Standar Deviasi", "Minimum", "Maksimum"),
Nilai = c(
round(mean(dur_data, na.rm = TRUE), 2),
median(dur_data, na.rm = TRUE),
modus(dur_data),
quantile(dur_data, 0.25, na.rm = TRUE),
quantile(dur_data, 0.75, na.rm = TRUE),
diff(range(dur_data, na.rm = TRUE)),
round(var(dur_data, na.rm = TRUE), 2),
round(sd(dur_data, na.rm = TRUE), 2),
min(dur_data, na.rm = TRUE),
max(dur_data, na.rm = TRUE)
)
)
kable(stats_dur, caption = "Statistik Deskriptif: Durasi Film (menit)") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "bordered"),
full_width = FALSE
)| Statistik | Nilai |
|---|---|
| Mean | 99.58 |
| Median | 98.00 |
| Modus | 90.00 |
| Q1 (Kuartil 1) | 87.00 |
| Q3 (Kuartil 3) | 114.00 |
| Range | 309.00 |
| Varians | 799.94 |
| Standar Deviasi | 28.28 |
| Minimum | 3.00 |
| Maksimum | 312.00 |
ggplot(movie_data, aes(x = duration_minutes)) +
geom_histogram(binwidth = 10, fill = "#E50914", color = "white", alpha = 0.85) +
geom_vline(xintercept = mean(dur_data, na.rm = TRUE),
color = "blue", linetype = "dashed", linewidth = 1) +
geom_vline(xintercept = median(dur_data, na.rm = TRUE),
color = "darkgreen", linetype = "solid", linewidth = 1) +
annotate("text",
x = mean(dur_data, na.rm = TRUE) + 12, y = 450,
label = paste("Mean =", round(mean(dur_data, na.rm = TRUE), 1)),
color = "blue", size = 3.5) +
annotate("text",
x = median(dur_data, na.rm = TRUE) - 20, y = 380,
label = paste("Median =", median(dur_data, na.rm = TRUE)),
color = "darkgreen", size = 3.5) +
labs(
title = "Histogram Durasi Film Netflix",
x = "Durasi (Menit)",
y = "Frekuensi"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"))Histogram Durasi Film Netflix
Interpretasi: Distribusi durasi film mendekati simetris dengan puncak di kisaran 90-100 menit. Terdapat outlier di sisi kanan (film >180 menit, kemungkinan dokumenter atau film epik). Durasi rata-rata ini sesuai dengan standar industri perfilman internasional.
ggplot(movie_data, aes(x = duration_minutes)) +
geom_density(fill = "#E50914", alpha = 0.6, color = "#990000") +
geom_vline(xintercept = mean(dur_data, na.rm = TRUE),
color = "blue", linetype = "dashed", linewidth = 1) +
geom_vline(xintercept = median(dur_data, na.rm = TRUE),
color = "darkgreen", linetype = "solid", linewidth = 1) +
annotate("text",
x = mean(dur_data, na.rm = TRUE) + 15, y = 0.014,
label = paste("Mean =", round(mean(dur_data, na.rm = TRUE), 1)),
color = "blue", size = 3.5) +
annotate("text",
x = median(dur_data, na.rm = TRUE) - 20, y = 0.012,
label = paste("Median =", median(dur_data, na.rm = TRUE)),
color = "darkgreen", size = 3.5) +
labs(
title = "Density Plot Durasi Film Netflix",
x = "Durasi (Menit)",
y = "Densitas"
) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"))Density Plot Durasi Film Netflix
Interpretasi: Kurva densitas berbentuk unimodal dengan puncak di sekitar 90 menit. Ekor panjang ke kanan menunjukkan kemiringan positif ringan akibat film berdurasi sangat panjang. Distribusi ini mendekati normal sehingga uji parametrik dapat diterapkan untuk analisis lebih lanjut.
ggplot(
movie_data %>% filter(rating_group != "Lainnya"),
aes(x = rating_group, y = duration_minutes, fill = rating_group)
) +
geom_boxplot(
outlier.colour = "red", outlier.shape = 16,
outlier.size = 2, alpha = 0.8
) +
stat_summary(
fun = mean, geom = "point",
shape = 23, size = 3,
fill = "white", color = "black"
) +
scale_fill_manual(values = c(
"Anak-Anak" = "#FFD700",
"Remaja" = "#FF8C00",
"Dewasa" = "#E50914"
)) +
labs(
title = "Boxplot Durasi Film Netflix per Kelompok Rating",
subtitle = "Titik putih (diamond) = nilai Mean | Titik merah = Outlier",
x = "Kelompok Rating",
y = "Durasi (Menit)"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
plot.subtitle = element_text(hjust = 0.5),
legend.position = "none"
)Boxplot Durasi Film Netflix per Kelompok Rating
Interpretasi:
Perbedaan durasi antar kelompok dapat diuji lebih lanjut menggunakan uji ANOVA untuk mengetahui apakah perbedaannya signifikan secara statistik.
## ===== Identifikasi Bentuk Sebaran =====
## >> Release Year:
## Mean : 2014.18
## Median : 2017
## Modus : 2018
if (mean(year_data, na.rm = TRUE) < median(year_data, na.rm = TRUE)) {
cat(" Kesimpulan: Mean < Median -> MIRING KE KIRI (Negative Skew)\n\n")
} else {
cat(" Kesimpulan: Mean > Median -> MIRING KE KANAN (Positive Skew)\n\n")
}## Kesimpulan: Mean < Median -> MIRING KE KIRI (Negative Skew)
## >> Duration (menit):
## Mean : 99.58
## Median : 98
## Modus : 90
if (mean(dur_data, na.rm = TRUE) < median(dur_data, na.rm = TRUE)) {
cat(" Kesimpulan: Mean < Median -> MIRING KE KIRI (Negative Skew)\n\n")
} else {
cat(" Kesimpulan: Mean > Median -> MIRING KE KANAN (Positive Skew)\n\n")
}## Kesimpulan: Mean > Median -> MIRING KE KANAN (Positive Skew)
## ===== Deteksi Outlier: Durasi Film =====
Q1_dur <- quantile(dur_data, 0.25, na.rm = TRUE)
Q3_dur <- quantile(dur_data, 0.75, na.rm = TRUE)
IQR_dur <- Q3_dur - Q1_dur
BB <- Q1_dur - 1.5 * IQR_dur
BA <- Q3_dur + 1.5 * IQR_dur
cat("Q1 (Kuartil 1) :", Q1_dur, "menit\n")## Q1 (Kuartil 1) : 87 menit
## Q3 (Kuartil 3) : 114 menit
## IQR : 27 menit
## Batas Bawah : 46.5 menit
## Batas Atas : 154.5 menit
## Outlier bawah : 248 film
## Outlier atas : 201 film
rekap <- data.frame(
Variabel = c("Release Year", "Duration (menit)"),
Mean = c(round(mean(year_data, na.rm = TRUE), 2),
round(mean(dur_data, na.rm = TRUE), 2)),
Median = c(median(year_data, na.rm = TRUE),
median(dur_data, na.rm = TRUE)),
Modus = c(modus(year_data),
modus(dur_data)),
Q1 = c(quantile(year_data, 0.25, na.rm = TRUE),
quantile(dur_data, 0.25, na.rm = TRUE)),
Q3 = c(quantile(year_data, 0.75, na.rm = TRUE),
quantile(dur_data, 0.75, na.rm = TRUE)),
Range = c(diff(range(year_data, na.rm = TRUE)),
diff(range(dur_data, na.rm = TRUE))),
Varians = c(round(var(year_data, na.rm = TRUE), 2),
round(var(dur_data, na.rm = TRUE), 2)),
Std_Dev = c(round(sd(year_data, na.rm = TRUE), 2),
round(sd(dur_data, na.rm = TRUE), 2))
)
kable(
rekap,
caption = "Rekapitulasi Statistik Deskriptif",
col.names = c("Variabel", "Mean", "Median", "Modus",
"Q1", "Q3", "Range", "Varians", "Std. Deviasi")
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "bordered"),
full_width = TRUE
) %>%
column_spec(1, bold = TRUE)| Variabel | Mean | Median | Modus | Q1 | Q3 | Range | Varians | Std. Deviasi |
|---|---|---|---|---|---|---|---|---|
| Release Year | 2014.18 | 2017 | 2018 | 2013 | 2019 | 96 | 77.81 | 8.82 |
| Duration (menit) | 99.58 | 98 | 90 | 87 | 114 | 309 | 799.94 | 28.28 |
Berdasarkan analisis statistika deskriptif terhadap dataset Netflix Movies and TV Shows, diperoleh empat temuan utama. Pertama, konten Netflix didominasi oleh Movie (~69%) dibandingkan TV Show (~31%), mencerminkan fokus platform pada konten film. Kedua, rating TV-MA adalah yang paling dominan (~36%), menunjukkan bahwa segmen utama Netflix adalah penonton dewasa. Ketiga, mayoritas konten dirilis antara 2015-2021 dengan distribusi miring ke kiri, yang disebabkan oleh adanya konten lama sebagai outlier. Keempat, rata-rata durasi film berkisar 90-100 menit dengan distribusi mendekati simetris, di mana film berrating dewasa umumnya berdurasi lebih panjang dibandingkan film anak-anak.
Sebagai langkah lanjutan, perbedaan durasi antar kelompok rating dapat diuji menggunakan uji ANOVA atau Kruskal-Wallis untuk menentukan signifikansi statistiknya.
Dibuat dengan R Markdown