Исследование набора данных Netflix 2020 с помощью R Markdown (EDA)

Набор данных состоит из телешоу и фильмов, доступных на Netflix по состоянию на 2019 год и часть 2020 года. Вы можете скачать его по этой ссылке: https://github.com/ygterl/EDA-Netflix-2020-in-R собранные из Flixable, сторонней поисковой системы Netflix.

Исследование и изменение набора данных

В этой части мы проверим наблюдения, переменные и значения наших данных. Этот раздел состоит из 3 частей; чтение, очистка данных и визуализация данных Для визуализации данных используются 3 разных библиотеки (ggplot2, ggpubr, plotly).

Чтение данных

Давайте прочитаем данные и переименуем их как «netds», чтобы было удобнее и проще кодировать функции. Ниже мы должны написать na.string = c («», «NA»), потому что некоторые значения наших данных пусты или имеют значение NA. Если мы не укажем их в начале функции чтения, мы не сможем достичь недостающих значений в будущих шагах.

* Почему stringsAsFactors по умолчанию не имеет значения FALSE?

Аргумент «stringsAsFactors» является аргументом для «data. frame () ’в R. Это логика, которая указывает, следует ли рассматривать строки во фрейме данных как факторные переменные или просто как простые строки.

netds <- read.csv("netflix_titles.csv", na.strings = c("", "NA"), stringsAsFactors =FALSE)

В наборе данных 6234 наблюдения 12 следующих переменных, описывающих телешоу и фильмы:

library(plotly)
values_table1 <- rbind(c('show_id', 'type', 'title', 'director', 'cast', 'country', 'date_added', 'release_year', 'rating' , 'duration', 'listed_in', 'description'), c("Unique ID for every Movie / TV Show", 
     "Identifier - A Movie or TV Show", 
     "Title of the Movie or TV Show", 
     "Director of the Movie /TV Show", 
    "Actors involved in the Movie / TV Show",
    "Country where the movie / show was produced",
    "Added date on Netflix",
    "Actual release year of the Movie / TV Show",
    "Rating type of the Movie or TV Show",
    "Total Duration - in minutes or number of seasons",
    "Genere",
    "The summary description"))
fig_table1 <- plot_ly(
  type = 'table',
  columnorder = c(1,2),
  columnwidth = c(12,12),
  header = list(
    values = c('<b>VARIABLES</b><br>', '<b>DESCRIPTION</b>'),
    line = list(color = '#506784'),
    fill = list(color = '#119DFF'),
    align = c('left','center'),
    font = list(color = 'white', size = 12),
    height = 40
  ),
  cells = list(
    values = values_table1,
    line = list(color = '#506784'),
    fill = list(color = c('#25FEFD', 'white')),
    align = c('left', 'left'),
    font = list(color = c('#506784'), size = 12),
    height = 30
    ))
fig_table1

Очистка данных

В качестве первого шага очистки мы можем удалить ненужные переменные и части данных, такие как переменная show_id. Также переменная описания не будет использоваться для анализа или визуализации, но может быть полезна для дальнейшего анализа или интерпретации.

netds$show_id <- NULL

Рейтинг - это категориальная переменная, поэтому мы изменим его тип.

netds$rating <- as.factor(netds$rating)

Мы также можем изменить формат даты переменной date_added.

library(lubridate)
netds$date_added <- mdy(netds$date_added)

«Type» и «Listed_in» должны быть категориальными переменными.

netds$listed_in <- as.factor(netds$listed_in)
netds$type <- as.factor(netds$type)

Отсутствующие значения могут быть проблемой для следующих шагов. Следовательно, мы должны проверить их перед анализом, а затем мы можем заполнить недостающие значения некоторых переменных, если это необходимо.

# printing the missing values by creating a new data frame
data.frame("Variable"=c(colnames(netds)), "Missing Values"=sapply(netds, function(x) sum(is.na(x))), row.names=NULL)

Мы ясно видим, что пропущенные значения имеют место в переменных Director, Cast, Country, data_added и rating. Поскольку рейтинг является категориальной переменной с 14 уровнями, мы можем заполнить (приблизить) недостающие значения для рейтинга с помощью режима.

#function to find a mode
mode <- function(v) {
   uniqv <- unique(v)
   uniqv[which.max(tabulate(match(v, uniqv)))]
}
netds$rating[is.na(netds$rating)] <- mode(netds$rating)

Еще раз проверьте наполнение

Теперь мы собираемся отбросить недостающие значения там, где это будет необходимо. Мы также удаляем повторяющиеся строки в наборе данных на основе переменных «title», «country», «type», «release_year».

#title, country, type and release_year
library(dplyr)
netds=distinct(netds, title, country, type, release_year, .keep_all = TRUE)

Процесс очистки данных завершен. Теперь можно приступить к визуализации.

Визуализация данных

Количество контента Netflix по типу

На первом рисунке библиотека ggplot2 используется для визуализации данных с помощью простой гистограммы. В части кода будут описаны некоторые аргументы функций.

library(tibble)
library(dplyr)
library(ggplot2)
# Here we created a new table by the name of "amount_by_type" and applied some filter by using dplyr library. Primarly, group_by() function is used to select variable and then used summarise() function with n() to count number of TV Shows and Movies.
amount_by_type <- netds %>% group_by(type) %>% summarise(
  count = n())
# In ggplot2 library, the code is created by two parts. First one is ggplot(), here we have to specify our arguments such as data, x and y axis and fill type. then continue with + and type of the graph will be added by using geom_graphytype.
figure00  <- ggplot(data = amount_by_type, aes(x= type, y= count, fill= type))+ 
  geom_bar(colour ="black", size= 0.8, fill = "dark green" ,  stat = "identity")+
  guides(fill= FALSE)+
  xlab("Netflix Content by Type") + ylab("Amount of Netflix Content")+
  ggtitle("Amount of Netflix Content By Type")

Как видно из вышесказанного, фильмов на Netflix более чем в 2 раза больше, чем телешоу.

Количество контента Netflix по странам первой десятки

# 1: split the countries (ex: "United States, India, South Korea, China" form to 'United States' 'India' 'South Korea' 'China') in the country column by using strsplit() function and then assign this operation to "k" for future use.
k <- strsplit(netds$country, split = ", ")
# 2: Created a new data frame by using data.frame() function. First column should be type = second one country=. Created type column by using rep() function. The function replicates the values in netds$type depends on the length of each element of k. we used sapply()) function. Now k is our new data in sapply(). it means that calculate the length of each element of the k list so that we create type column. In the country column, we used just unlist() function. It simply converts the list to vector with all the atomic components are being preserved.
netds_countries<- data.frame(type = rep(netds$type, sapply(k, length)), country = unlist(k))
# 3: Changed the elements of country column as character by using as.charachter() function.
netds_countries$country <- as.character(netds_countries$country)
# 4: we created new grouped data frame by the name of amount_by_country. NA.omit() function deletes the NA values on the country column/variable. Then we groupped countries and types by using group_by() function (in the "dplyr" library). After that used summarise() function to summarise the counted number of observations on the new "count" column by using n() function.
amount_by_country <- na.omit(netds_countries) %>%
  group_by(country, type) %>%
  summarise(count = n())
# 5: Actually we can use the "amount_by_country" data frame to observe number of TV Show or Movie in countries. However, this list is too big to be visualized. Thus, we will create a new data frame as table to see just top 10 countries by the name of "u".
# reshape() function will be used to create a reshaped grouped data. amount_by_country is used as data in the function. In this function, we will describe id variable, names of the value, time variable, and direction. Direction is character string, partially matched to either "wide" to reshape to wide format, or "long" to reshape to long format. Then we applied arrange() function to the reshaped grouped data. The dplyr function arrange() can be used to reorder (or sort) rows by one or more variables. In this part we sort count.movie column as descending.
# To check to arguments and detailed descriptions of functions please use to help menu or google.com
# After the arrange function, top_n() function is used to list the specified number of rows.
u <- reshape(data=data.frame(amount_by_country),idvar="country",
                          v.names = "count",
                          timevar = "type",
                          direction="wide") %>% arrange(desc(count.Movie)) %>%
                          top_n(10)
# 6: names of the second and third columns are changed by using names() function as seen below.
names(u)[2] <- "Number_of_Movies"
names(u)[3] <- "Number_of_TV_Shows"
# 7: In the arrange() function we sorted our count.movie columns as descending but, now, we want to change this sort depends on the total values of "number of Movies" and "number of TV Shows". To sort a data frame in R, use the order() function. By default, sorting is ASCENDING. Therefore, we have to specify as descending. + is used to specify total operation.
u <- u[order(desc(u$Number_of_Movies +u$Number_of_TV_Shows)),]
# 8: Now we can create our graph by using ggplot2 library. First argument of the ggplot function is our data.frame, then we specified our variables in the aes() function. coloured the graphy depends on the countries. Then typeof the graph is writed as geom_point and dot size specified as 5. After that we named x and y axis. Title of the graph is wroted by using ggtitle() function. 
  
library(ggplot2)
figure000 <- ggplot(u, aes(Number_of_Movies, Number_of_TV_Shows, colour=country))+ 
  geom_point(size=5)+
  xlab("Number of Movies") + ylab("Number of TV Shows")+
  ggtitle("Amount of Netflix Content By Top 10 Country")
ggplotly(figure000, dynamicTicks = T)

Мы видим, что США - явный лидер по количеству контента на Netflix.

Количество контента Netflix по времени

# 0: To see number contents by time we have to create a new data.frame. This process is a little tiring. Maybe there is a short way but I couldn't find it. Lets start!
# 1: Title column take place in our dataframe as character therefore I have to convert it to tbl_df format to apply the function below. If this column remains in character format and I want to implement the function, R returns an error: " Error in UseMethod("group_by_") : no applicable method for 'group_by_' applied to an object of class "character""     Therefore, first I assign it title column to f then convert the format as tibble and then assign it again to title column.
f <- netds$title
f <-tibble(f)
netds$title <- f
# 2: new_date variable created by selecting just years. In this way, we can analyze and visualise the data more easy
library(lubridate)
netds$new_date <- year(netds$date_added)
# 2: df_by_date crated as a new grouped data frame. Titles are grouped depending the new_date(year) and then na.omit function applied to date column to remove NA values. Finally, number of added contents in a day calculated by using summarise() and n() functions.
df_by_date <- netds$title %>% 
  group_by(netds$new_date, netds$type) %>% 
  na.omit(netds$new_date) %>% 
  summarise(added_content_num = n())
# 3: now we will visualize our new grouped data frame.
library(ggplot2)
Type<- df_by_date$`netds$type`
Date <- df_by_date$`netds$new_date`
Content_Number <- df_by_date$added_content_num
g1<- ggplot(df_by_date, aes(Date, Content_Number))+
  geom_line(aes(colour = Type), size = 2)+ 
  geom_point() + 
  xlab("Date") + 
  ylab("Number of Content")+
  ggtitle("Amount of Netflix Content By Time")
ggplotly(g1, dynamicTicks = T)

Сверху мы видим, что с 2016 года общий объем контента рос в геометрической прогрессии. Мы также замечаем, насколько быстро количество фильмов на Netflix превысило количество телешоу. Причина спада в 2020 году заключается в том, что имеющиеся у нас данные заканчиваются началом 2020 года. В начале 2020 года количество производимых ингредиентов невелико. Прежде чем что-то сказать о 2020 году, мы должны увидеть данные на конец года.

Количество контента по рейтингу

# Here plotly library used to visualise data. To see the graph in chunk output or console you have to assign it to somewhere such as "fig"
library(plotly)
data <-netds$title %>% 
  group_by(netds$rating) %>% 
  summarise(content_num = n())
names(data) [1] <- "rating"
names(data) [2] <- "content"
# From the above, we created our new table to use in graph
figure2 <- plot_ly(data, labels = ~rating, values = ~content, type = 'pie')
# In the first part of visualisation, again, we have to specify our data labels, values,  x ad y axis and type of graph.
# In second part, adding title and other arguments of graph.
figure2 <- figure2 %>% layout(title = 'Amount of Content by Rating',
         xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
         yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
figure2

Количество контента по рейтингу (фильм или телешоу)

# data preparation 
data2 <-netds$title %>% 
  group_by(netds$rating, netds$type)%>% 
  summarise(content_num = n())
names(data2) [1] <- "rating"
names(data2) [2] <- "type"
names(data2) [3] <- "content"
newdata2 <- reshape(data=data.frame(data2),idvar="rating",
                          v.names = "content",
                          timevar = "type",
                          direction="wide")
names(newdata2)[2] <- "Movie"
names(newdata2)[3] <- "TV Show"
newdata2$`TV Show`[is.na(newdata2$`TV Show`)] <- print(0)
# visualisation
library(plotly)
rating <- newdata2$rating
Movie <- newdata2$Movie
Tv_Show <- newdata2$`TV Show`
figure3 <- plot_ly(newdata2, x = ~rating, y = ~Movie, type = 'bar', name = 'Movie')
figure3 <- figure3 %>% add_trace(y = ~Tv_Show, name = 'TV Show')
figure3 <- figure3 %>% layout(yaxis = list(title = 'Count'),
                        barmode = 'stack', 
                        title="Amount of Content By Rating (Movie vs. TV Show)")
figure3

20 лучших жанров на NETFLIX

# data preparation
library(crayon)
# before apply to strsplit function, we have to make sure that type of the variable is character.
netds$listed_in<- as.character(netds$listed_in)
t20 <- strsplit(netds$listed_in, split = ", ")
count_listed_in<- data.frame(type = rep(netds$type, 
                                        sapply(t20, length)), 
                             listed_in = unlist(t20))
count_listed_in$listed_in <- as.character(gsub(",","",count_listed_in$listed_in))
df_count_listed_in <- count_listed_in %>% 
                            group_by(listed_in) %>% 
                            summarise(count = n()) %>% 
                            top_n(20)
# visualisation
figure4 <- plot_ly(df_count_listed_in, x= ~listed_in, y= ~df_count_listed_in$count, type = "bar" )
figure4 <- figure4 %>% layout(xaxis=list(categoryorder = "array",categoryarray =df_count_listed_in$listed_in, title="Genre"), yaxis = list(title = 'Count'),title="20 Top Genres On Netflix")
figure4

Топ-20 директоров по количеству контента на Netflix

# data preparation
dir20 <- strsplit(netds$director, split = ", ")
titles_director <-  data.frame(type= rep(netds$type, sapply(dir20, length)), director = unlist(dir20))
titles_director$director <- as.character(gsub(","," ", titles_director$director))
titles_director <- na.omit(titles_director) %>%  
                          group_by(director) %>% 
                          summarise(count = n()) %>% 
                          arrange(desc(count)) %>% 
                          top_n(20)
titles_director <- as.data.frame(titles_director)
library(tibble)
titles_director<- titles_director %>% 
                  remove_rownames %>% 
                  column_to_rownames(var = "director")
# visualisation as table
fig_table2 <- plot_ly(
  type = 'table',
  header = list(
    values = c( '<b>Director<b>', names(titles_director)),
  align = c('left', rep('center', ncol(titles_director))),
  line = list(width = 1, color = 'black'),
  fill = list(color = '#506784'),
  font = list(family = "Arial", size = 14, color = "white")
  ),
  cells = list(
    values = rbind(
      rownames(titles_director), 
      t(as.matrix(unname(titles_director)))
    ),
    align = c('left', rep('center', ncol(titles_director))),
    line = list(color = "black", width = 1),
    fill = list(color = c('white')),
    font = list(family = "Arial", size = 12, color = c("black"))
  ))
fig_table2

Вы можете загрузить набор данных и документ Rmarkdown через мой профиль github: https://github.com / ygterl / EDA-Netflix-2020-in-R

#ExploratoryDataAnalysis #EDA #DataScience #Datavisualisation #Netflix

Пожалуйста, нажмите моя средняя страница, чтобы получать информацию о еженедельных статьях…