### Hanjoon Ko
### Deuxième viz
### M1 DES 22/23
### version modifiée
# Attaching packages ─────────────────────────────────────────────────────────────────────────── tidyverse 1.3.2 ──
# ✔ ggplot2 3.4.1 ✔ dplyr 1.0.10
# ✔ tibble 3.1.8 ✔ stringr 1.4.1
# ✔ tidyr 1.2.1 ✔ forcats 0.5.2
# ✔ purrr 1.0.1
# Conflicts ────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
# ✖ dplyr::filter() masks stats::filter()
# ✖ dplyr::lag() masks stats::lag()
library(readr)
library(skimr)
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.4.1 ✔ dplyr 1.0.10
## ✔ tibble 3.1.8 ✔ stringr 1.4.1
## ✔ tidyr 1.2.1 ✔ forcats 0.5.2
## ✔ purrr 1.0.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
Netflix <- read_csv("C:/Users/Ko/OneDrive/Nanterre/S2/Visualisation/cours de viz/NetflixOriginals.csv")
## Rows: 584 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): Title, Genre, Premiere, Language
## dbl (2): Runtime, IMDB Score
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
View(Netflix)
# Le nom de dataset : Netflix Original Films & IMDB Scores
# URL : https://www.kaggle.com/datasets/luiscorter/netflix-original-films-imdb-scores?select=NetflixOriginals.csv
# L'analyse générale -------------------------------------------------------
skim(Netflix)
Data summary
| Name |
Netflix |
| Number of rows |
584 |
| Number of columns |
6 |
| _______________________ |
|
| Column type frequency: |
|
| character |
4 |
| numeric |
2 |
| ________________________ |
|
| Group variables |
None |
Variable type: character
| Title |
0 |
1 |
2 |
105 |
0 |
584 |
0 |
| Genre |
0 |
1 |
3 |
36 |
0 |
115 |
0 |
| Premiere |
0 |
1 |
11 |
18 |
0 |
390 |
0 |
| Language |
0 |
1 |
4 |
26 |
0 |
38 |
0 |
Variable type: numeric
| Runtime |
0 |
1 |
93.58 |
27.76 |
4.0 |
86.0 |
97.00 |
108 |
209 |
▁▂▇▁▁ |
| IMDB Score |
0 |
1 |
6.27 |
0.98 |
2.5 |
5.7 |
6.35 |
7 |
9 |
▁▂▇▇▁ |
# Les données consistent de 584 films produits par Netflix jusqu'au 1 juin 2021
# Il y a 6 colonnes : Title, Genre, Premiere (la date de sortie), Language, Runtime, IMDB Score. Dans cet analyse, on va focaliser sur IMDB Score
# Il y a 115 genres incluant les films documentaires
# 38 langues sont offertes. Certains films sont disponibles en plusieurs de langues (ex. l'anglais/l'hindi)
# La durée moyenne de films est 93.6 minutes. Il y a une donnée atypique qui dure 209 minutes (The Irishman)
Netflix <- Netflix %>%
filter(Runtime < 209)
# On a supprimé une donnée trop atypique qui dure 209 minutes
Netflix %>%
arrange(-`IMDB Score`)
## # A tibble: 583 × 6
## Title Genre Premi…¹ Runtime IMDB …² Langu…³
## <chr> <chr> <chr> <dbl> <dbl> <chr>
## 1 David Attenborough: A Life on Our Plan… Docu… Octobe… 83 9 English
## 2 Emicida: AmarElo - It's All For Yester… Docu… Decemb… 89 8.6 Portug…
## 3 Springsteen on Broadway One-… Decemb… 153 8.5 English
## 4 Ben Platt: Live from Radio City Music … Conc… May 20… 85 8.4 English
## 5 Taylor Swift: Reputation Stadium Tour Conc… Decemb… 125 8.4 English
## 6 Winter on Fire: Ukraine's Fight for Fr… Docu… Octobe… 91 8.4 Englis…
## 7 Cuba and the Cameraman Docu… Novemb… 114 8.3 English
## 8 Dancing with the Birds Docu… Octobe… 51 8.3 English
## 9 13th Docu… Octobe… 100 8.2 English
## 10 Disclosure: Trans Lives on Screen Docu… June 1… 107 8.2 English
## # … with 573 more rows, and abbreviated variable names ¹Premiere,
## # ²`IMDB Score`, ³Language
# Le score moyen d'IMDB est 6.27 sur 9. Le film le mieux noté est David Attenborough: A Life on Our Planet
library(png)
library(grid)
setwd("C:/Users/Ko/OneDrive/Documents/")
mon_image <- readPNG("IMDB.png") %>%
rasterGrob(interpolate=TRUE)
# Je prépare une image du logo d'IMDB pour ajouter dans le plot
# Viz 1 -------------------------------------------------------------------
library(ggplot2)
library(ggforce)
library(plotly)
##
## Attachement du package : 'plotly'
##
## L'objet suivant est masqué depuis 'package:ggplot2':
##
## last_plot
##
## L'objet suivant est masqué depuis 'package:stats':
##
## filter
##
## L'objet suivant est masqué depuis 'package:graphics':
##
## layout
library(htmlwidgets)
### La relation entre la durée de films et le score d'IMDB
viz1 <- ggplot(Netflix) +
aes(x = Runtime, y = `IMDB Score`, colour = `IMDB Score`) +
geom_point(shape = "square",
size = 3L) +
scale_color_viridis_c(option = "viridis", direction = 1) +
labs(title = "La relation entre la durée de film et le score d'IMDB", subtitle = "Films produits par Netflix jusqu'à juin 2021",
color = "Score", x = "Durée (min)", y = "IMDB Score (sur 9.0)") +
geom_hline(aes(yintercept = mean(`IMDB Score`)), linewidth = 1.3, color = "firebrick", linetype ="dashed") + # hline pour visualiser la moyenne du score
annotate("text", x = 4, y = 6.1,
label = "la moyenne (6.27)",
color = "firebrick", size = 4, fontface = 3) +
annotate("text", x = 140, y = 2,
label = "Université Paris Nanterre DES 22/23
Deuxième visualisation - Hanjoon Ko",
color = "black", size = 3) +
annotate("text", x = 0, y = 9,
label = "R = -0.05",
color = "black", size = 4, fontface = 2) +
annotation_custom(mon_image,
xmin=140, xmax=160,
ymin=2.5, ymax=3) + # Le logo d'IMDB est ajouté pour mettre en avant de la source de score
theme_light()
viz1

### VIZ
ggplotly(viz1, tooltip = c("x","y")) %>%
layout(title = list(text = paste0("La relation entre la durée de film et le score d'IMDB",
"<br>",
"<sup>",
"Films produits par Netflix jusqu'à juin 2021",'</sup>')))
## Warning in geom2trace.default(dots[[1L]][[1L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomCustomAnn() has yet to be implemented in plotly.
## If you'd like to see this geom implemented,
## Please open an issue with your example code at
## https://github.com/ropensci/plotly/issues
saveWidget(ggplotly(viz1, tooltip = c("x","y")) %>%
layout(title = list(text = paste0("La relation entre la durée de film et le score d'IMDB",
"<br>",
"<sup>",
"Films produits par Netflix jusqu'à juin 2021",'</sup>')))
, "viz1_hanjoon.html", selfcontained = FALSE)
## Warning in geom2trace.default(dots[[1L]][[1L]], dots[[2L]][[1L]], dots[[3L]][[1L]]): geom_GeomCustomAnn() has yet to be implemented in plotly.
## If you'd like to see this geom implemented,
## Please open an issue with your example code at
## https://github.com/ropensci/plotly/issues
### COR
cor(Netflix$Runtime, Netflix$`IMDB Score`, use = "complete.obs")
## [1] -0.05294635
# R = -0.05
# On ne voit pas la relation entre la durée de films et le score
# Viz 2 -------------------------------------------------------------------
library(gifski)
library(gganimate)
### Est-ce la langue affecte-t-elle le score ?
skim(Netflix$Language)
Data summary
| Name |
Netflix$Language |
| Number of rows |
583 |
| Number of columns |
1 |
| _______________________ |
|
| Column type frequency: |
|
| character |
1 |
| ________________________ |
|
| Group variables |
None |
Variable type: character
Netflix <- Netflix %>%
mutate(Language2 = fct_collapse(Language,
Anglais = c("English/Japanese", "English", "English/Spanish", "English/Swedish",
"English/Taiwanese/Mandarin", "Thia/English", "English/Mandarin", "Khmer/English/French", "English/Hindi",
"Spanish/English", "English/Korean", "English/Arabic", "English/Russian", "English/Akan", "English/Ukranian/Russian"),
Européen = c("Dutch", "French", "Georgian", "German", "Norwegian", "Polish", "Portuguese", "Spanish/Basque",
"Spanish/Catalan", "Swedish", "Spanish", "Italian"),
Asiatique = c("Bengali", "Tamil", "Thai", "Filipino", "Hindi", "Indonesian", "Japanese", "Korean", "Malay",
"Marathi", "Turkish")))
# Il y a 38 différents langues disponibles incluant celles qui utilisent à la fois plusieurs de langues (ex. Spanish / English)
# J'ai divisé toutes les langues par 3 comme l'anglais, l'européen et l'asiatique vu que l'anglais est la langue plus utilisée
view(Netflix)
Netflix_ang <- Netflix %>%
filter(Language2 == "English")
Netflix_eu_asia <- Netflix %>%
filter(Language2 != "English")
skim(Netflix_ang)
Data summary
| Name |
Netflix_ang |
| Number of rows |
0 |
| Number of columns |
7 |
| _______________________ |
|
| Column type frequency: |
|
| character |
4 |
| factor |
1 |
| numeric |
2 |
| ________________________ |
|
| Group variables |
None |
Variable type: character
| Title |
0 |
NaN |
NA |
NA |
0 |
0 |
0 |
| Genre |
0 |
NaN |
NA |
NA |
0 |
0 |
0 |
| Premiere |
0 |
NaN |
NA |
NA |
0 |
0 |
0 |
| Language |
0 |
NaN |
NA |
NA |
0 |
0 |
0 |
Variable type: factor
| Language2 |
0 |
NaN |
FALSE |
0 |
Asi: 0, Eur: 0, Ang: 0 |
Variable type: numeric
| Runtime |
0 |
NaN |
NaN |
NA |
NA |
NA |
NA |
NA |
NA |
|
| IMDB Score |
0 |
NaN |
NaN |
NA |
NA |
NA |
NA |
NA |
NA |
|
skim(Netflix_eu_asia) # Skim pour comparer la note des films en anglais avec celle des films en autres langues
Data summary
| Name |
Netflix_eu_asia |
| Number of rows |
583 |
| Number of columns |
7 |
| _______________________ |
|
| Column type frequency: |
|
| character |
4 |
| factor |
1 |
| numeric |
2 |
| ________________________ |
|
| Group variables |
None |
Variable type: character
| Title |
0 |
1 |
2 |
105 |
0 |
583 |
0 |
| Genre |
0 |
1 |
3 |
36 |
0 |
115 |
0 |
| Premiere |
0 |
1 |
11 |
18 |
0 |
390 |
0 |
| Language |
0 |
1 |
4 |
26 |
0 |
38 |
0 |
Variable type: factor
| Language2 |
0 |
1 |
FALSE |
3 |
Ang: 421, Eur: 93, Asi: 69 |
Variable type: numeric
| Runtime |
0 |
1 |
93.38 |
27.37 |
4.0 |
86.0 |
97.0 |
107.5 |
155 |
▁▁▅▇▁ |
| IMDB Score |
0 |
1 |
6.27 |
0.98 |
2.5 |
5.7 |
6.3 |
7.0 |
9 |
▁▂▇▇▁ |
viz2 <- Netflix %>%
ggplot() +
aes(x = Runtime, y = `IMDB Score`, colour = Language2) +
geom_point(shape = "circle",
size = 3L) +
scale_color_viridis_d(option = "viridis", direction = 1) +
labs(title = "La relation entre la langue de film et le score d'IMDB", subtitle = "Films produits par Netflix jusqu'à juin 2021",
caption = "Université Paris Nanterre DES 22/23
Deuxième Visualisation - Hanjoon Ko", color = "Language", x = "Durée (min)", y = "IMDB Score (sur 9.0)") +
geom_hline(aes(yintercept = mean(`IMDB Score`)), linewidth = 1, color = "firebrick", linetype ="dashed") +
annotate("text", x = 10, y = 6.1,
label = "la moyenne (6.27)",
color = "firebrick", size = 4, fontface = 3) +
annotate("text", x = 25, y = 2.4,
label = "La moyenne de score :
6.39 (L'anglais), 5.95 (L'européen / L'asiatique)",
color = "black", size = 4, fontface =2) +
annotation_custom(mon_image,
xmin=140, xmax=160,
ymin=2, ymax=3.5) +
theme_light()
viz2

viz2_anim <- (viz2 + transition_states(Language2, wrap = FALSE))
animate(viz2_anim, height = 600, width =800)

anim_save("viz2_hanjoon.gif")
# Il y a beaucoup plus de films qui sont disponibles en anglais (422) que ceux qui ne sont pas (117)
# Le moyen de score d'IMDB des films en anglais est plus haut (6.39 et 5.95)
# Conclusion --------------------------------------------------------------
# J'ai essayé de voir si la durée affecte la note d'IMDB, mais les films bien notés et les films mal notés sont distribués de manière écrêtée
# Le teste de corrélation l'a prouvé cette interprétation
# Donc Netflix n'a pas forcément besoin de prendre en considération la durée pour produire un film bien noté
# En deuxième lieu, j'ai comparé les films en anglais et les films en autres langues
# On a trouvé que le nombre des films en anglais est beaucoup plus
# Donc, pour produire un film bien noté, Netflix doit offrir l'anglais, même s'il est offrit avec d'autres langues ensemble (ex. l'anglais / l'hinde)