Analisando meus dados de consumo da Netflix, utilizando Python para programação, plotly para visualização interativa e expressões regulares (regex) para extração de informações de texto de colunas.
Python
EDA
Plotly
regex
Author
José Carlos S. Junior
Published
May 29, 2023
Introdução
Com o objetivo de demonstrar os procedimentos que realizo, desde a limpeza dos dados até a criação de gráficos para obter insights visuais, irei trabalhar com os dados da conta da Netflix utilizada por mim e minha família. Uma vantagem dessa abordagem é o fato de eu ter um conhecimento aprofundado sobre os indivíduos envolvidos nos dados, o que me permite identificar facilmente se os resultados estão condizentes com a realidade. Meu objetivo é realizar um tratamento adequado dos dados, garantindo que os resultados sejam coerentes e reflitam fielmente os padrões observados, levando em consideração meu conhecimento prévio dessas informações. Ao longo da análise, será possível verificar a consistência dos resultados e sua correspondência com a realidade, considerando meu conhecimento próximo e individual dessa realidade por trás da qual os dados foram gerados.
O processo de obtenção dos dados é simples. Basta solicitar os dados por meio da conta Netflix e, em seguida, uma pasta com arquivos será disponibilizada via e-mail para efetuar o download. O passo a passo pode ser verificado em Beginner Python Tutorial: Analyze Your Personal Netflix Data. Dentre os arquivos, utilizarei apenas o ViewingActivity.csv, localizado na pasta CONTENT_INTERACTION.
O código-fonte será ocultado neste projeto, com o objetivo de preservar informações pessoais. No entanto, os códigos utilizados na limpeza dos dados e na construção de gráficos permanecerão disponíveis ao longo do texto.
Descrição das variáveis
Entre os arquivos obtidos, há um PDF chamado “Folha de Capa” que contém as informações de cada variável. Para as variáveis da base presente no arquivo ViewingActivity.csv, temos o seguinte:
Profile Name – o nome do perfil usado para assistir.
Start Time – a data e a hora (UTC) do início da visualização.
Duration – a duração da sessão.
Attributes – esta coluna mostra detalhes adicionais das interações com o conteúdo acessado, quando disponíveis:
Autoplayed: user action: None” – significa que o assinante não interagiu com essa série ou filme.
Autoplayed: user action: Unspecified” – significa que o assinante interagiu com a série ou o filme (clicando na imagem da caixa e visualizando a página da série ou do filme enquanto é apresentado o conteúdo automático) ou que assistiu ao conteúdo automático por mais de 2 minutos.
Autoplayed: user action: User_Interaction” – significa que o assinante interagiu com a série ou o filme em um navegador clicando nos controles do player ou utilizando os atalhos do teclado.
View was hidden – indica que a série ou filme foi marcado como “Ocultar do histórico do que foi assistido” nas configurações da conta.
Has branched playback – indica que o assinante pode escolher opções enquanto assiste ao título, para controlar o que acontece em seguida.
Title – a série ou o filme assistido.
Supplemental Video Type – vídeos que não sejam uma série ou um filme, como trailers ou montagens.
A referência “N/A” significa “não se aplica”.
Device Type – o tipo de aparelho utilizado para acessar a série ou o filme.
Bookmark – a posição de visualização mais recente (em relação à duração total da série ou do filme) da sessão de reprodução específica de uma série ou um filme.
Latest Bookmark – indica se o marcador é a posição de visualização mais recente (em relação à duração total da série ou do filme) na sessão de reprodução mais recente de uma série ou filme.
Not latest view – indica que uma determinada sessão de reprodução não é a reprodução mais recente da série ou do filme e que, portanto, o marcador não é o mais recente.
Country – o país de onde a série ou o filme foi assistido. As partir de 1º de abril de 2018, para assinantes na União Europeia que viajam por até 60 dias de um país para outros países da União Europeia, este é o país em que a conta foi criada e não o país em que a série ou o filme foi assistido.
As variáveis Attributes, Bookmark e Latest Bookmark não serão consideradas, pois não consegui compreender claramente a informação que cada uma representa devido às suas descrições. Além disso, como minha família nunca saiu do país, a variável Country também será desconsiderada.
Tratamento dos dados
Inicialmente, após carregar os dados, transformei os nomes das colunas em letras minúsculas, seguindo as boas práticas de análise. Ao verificar as dimensões da base de dados, podemos observar pelo Output 1 que temos 10.974 observações e 10 variáveis, sem nenhum caso duplicado.
Code
# Carrega as bibliotecas para manipulação dos dadosimport pandas as pdimport numpy as np# Carrega pacote para visualização de dadosimport plotly.express as pximport plotly.graph_objects as gofrom plotly.subplots import make_subplots# Regeximport re# Carrega os dadosdf_netflix = pd.read_csv("datasets/ViewingActivity.csv")# Nome das variáveis padronizadas para lowercasedf_netflix.columns = df_netflix.columns.str.lower()# Número de linhas e colunas da base (10974, 10)print('Número de linhas e colunas da base:', df_netflix.shape)# Nenhum caso duplicado encontradoprint('Casos duplicados na base:', df_netflix.duplicated().sum())
Número de linhas e colunas da base: (10974, 10)
Casos duplicados na base: 0
Output 1: Informações de dimensão da base de dados e detecção de casos duplicados.
No Output 2, são apresentadas as cinco primeiras linhas da base de dados. Uma observação importante é que, entre as variáveis a serem consideradas, as colunas title e device type contêm informações múltiplas que precisarão ser separadas posteriormente para uma análise mais precisa. Além disso, as variáveis start time e duration são dados relacionados a tempo e data, e serão tratadas como tal.
Code
# Print das cinco primeiras linhas da base dedf_netflix.head(5)
profile name
start time
duration
attributes
title
supplemental video type
device type
bookmark
latest bookmark
country
0
Mãe
2023-05-19 19:19:51
00:27:35
Autoplayed: user action: User_Interaction;
Black Knight: Temporada 1: Episódio 4 (Episódi...
NaN
Samsung 2018 Kant-M2 UHD TV (1.5G) Smart TV
00:27:39
00:27:39
BR (Brazil)
1
Mãe
2023-05-19 18:09:15
00:44:45
Autoplayed: user action: User_Interaction;
Black Knight: Temporada 1: Episódio 3 (Episódi...
NaN
Samsung 2018 Kant-M2 UHD TV (1.5G) Smart TV
00:44:50
00:44:50
BR (Brazil)
2
Mãe
2023-05-19 17:39:51
00:29:21
NaN
Black Knight: Temporada 1: Episódio 2 (Episódi...
NaN
Samsung 2018 Kant-M2 UHD TV (1.5G) Smart TV
00:47:02
00:47:02
BR (Brazil)
3
Mãe
2023-05-18 19:46:26
00:13:07
Autoplayed: user action: User_Interaction;
Black Knight: Temporada 1: Episódio 2 (Episódi...
NaN
Samsung 2018 Kant-M2 UHD TV (1.5G) Smart TV
00:17:43
Not latest view
BR (Brazil)
4
Mãe
2023-05-17 19:35:06
00:04:34
Autoplayed: user action: User_Interaction;
Black Knight: Temporada 1: Episódio 2 (Episódi...
NaN
Samsung 2018 Kant-M2 UHD TV (1.5G) Smart TV
00:04:38
Not latest view
BR (Brazil)
Output 2: Primeiras cinco linhas da base de dados.
Dados faltantes
Em relação aos dados faltantes, podemos notar pelo Output 3 que eles se concentram nas variáveis attributes e supplemental video type. Porém, como attributes não será considerada, minha preocupação passa a ser apenas com a variável supplemental video type.
Após refletir sobre a descrição e examinar as informações disponíveis nessa variável, pude perceber que supplemental video type identifica todos os tipos de conteúdo que não sejam filmes ou séries, atribuindo-lhes um label, como trailers ou teasers. No caso em que a linha se refere a um filme ou série, nenhum valor é atribuído e é representado como um dado faltante. Curiosamente, todos os 7804 casos identificados como dados faltantes no Output 3 são, na verdade, os dados de interesse (filmes e séries), enquanto os demais serão desconsiderados.
Code
# Tabela dos dados faltantespd.DataFrame(df_netflix.isnull().sum(), columns = ['Dados faltantes totais de cada coluna'])
Dados faltantes totais de cada coluna
profile name
0
start time
0
duration
0
attributes
4671
title
0
supplemental video type
7804
device type
0
bookmark
0
latest bookmark
0
country
0
Output 3: Dados faltantes de cada coluna.
Por curiosidade, no Output 4, podemos observar os totais de cada tipo de vídeo na base de dados, agora incluindo filmes e séries. Além disso, observe que o rótulo desses dados de interesse é agora classificado como “FILME OU SERIE”, ou seja, não faz distinção entre filmes e séries. Posteriormente, será interessante separar essas informações para uma análise mais detalhada.
Code
# Atribui 'FILME OU SERIE' aos dados faltantes para a variável 'supplemental video type'df_netflix['supplemental video type'].fillna('FILME OU SERIE', inplace =True)# Tabela dos totais de cada tipo de video(pd.DataFrame(df_netflix['supplemental video type'].value_counts()). rename(columns = {'supplemental video type': 'Totais de cada tipo de video'}))
Totais de cada tipo de video
FILME OU SERIE
7804
HOOK
2060
TRAILER
838
TEASER_TRAILER
224
RECAP
19
PREVIEW
13
PROMOTIONAL
10
MARKETING_TRAILER
2
BUMPER
2
CINEMAGRAPH
2
Output 4: Totais de cada tipo de video identificados na coluna supplemental video type.
No Output 5, temos uma verificação dos tipos de vídeos encontrados na variável supplemental video type, ao desconsiderar os tipos que não são de interesse na análise. Assim, a base de dados agora possui 7.804 observações.
Code
# Considera apenas os dados referentes a filmes ou sériesdf_netflix2 = df_netflix.query("`supplemental video type` == 'FILME OU SERIE'")print("Os tipos de videos na coluna 'supplemental video type' são:", df_netflix2['supplemental video type'].unique())
Os tipos de videos na coluna 'supplemental video type' são: ['FILME OU SERIE']
Output 5: Verificação dos tipos de videos na variável supplemental video type após o filtro “FILME OU SERIE”.
Variáveis de data e tempo
Anteriormente, mencionei sobre as variáveis start time e duration, que representam informações de data e tempo. Para a coluna start time, utilizei inicialmente o método to_datetime() da biblioteca pandas para convertê-la em um objeto manipulável de data, considerando o Tempo Universal Coordenado (UTC). Em seguida, realizei a conversão de UTC para o fuso horário Brazil/East, que corresponde ao fuso horário da minha localização e da minha família. Esse passo é importante para garantir que a análise seja realizada com informações corretas. Além disso, extraí os dias da semana da coluna start time e os armazenei em uma nova coluna chamada dias eng. Essa informação é retornada em inglês, e então criei outra coluna chamada dias pt para traduzir os dias para o português, utilizando um dicionário.
Já a variável duration representa o tempo de duração da sessão ou consumo de um filme ou série, a partir do momento especificado em start time. Nesse caso, extrai as informações de duração em minutos, horas e dias, e as armazenei nas novas colunas duration m, duration h e duration d, respectivamente.
No Output 6, é possível visualizar o tipo de objeto de cada coluna após os devidos tratamentos.
Code
# Atribui uma cópia da base até então para evitar warnings desnecessáriosdf_netflix2 = df_netflix2.copy()# Converte em objeto para manipulação de datas (considerando tempo universal coordenado UTC)df_netflix2['start time'] = pd.to_datetime(df_netflix2['start time'], utc =True)# Encaixa a variável 'start time' como índice df_netflix2 = df_netflix2.set_index('start time')# Converte do tempo universal coordenado para Brazil/Eastdf_netflix2.index = df_netflix2.index.tz_convert('Brazil/East')# Cria coluna com os dias da semanadf_netflix2['dias eng'] = df_netflix2.index.strftime('%A')# Retorna o index como coluna novamentedf_netflix2 = df_netflix2.reset_index()# Dicionário dos dias da semana em en para pt-br days_dictionary = {'Monday': 'Segunda-feira','Tuesday': 'Terça-feira','Wednesday': 'Quarta-feira','Thursday': 'Quinta-feira','Friday': 'Sexta-feira','Saturday': 'Sábado','Sunday': 'Domingo'}# Coluna com os dias da semana em pt-brdf_netflix2['dias pt'] = df_netflix2['dias eng'].map(days_dictionary)# Ordem em que os dias da semana serão definidosordem_diasdasemana = ['Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado', 'Domingo']# Converte a variável 'dias pt' para categórica ordinaldf_netflix2['dias pt'] = pd.Categorical(df_netflix2['dias pt'], categories = ordem_diasdasemana, ordered =True)# Converte a duração para minutosdf_netflix2['duration m'] = pd.to_timedelta(df_netflix2['duration']).dt.total_seconds() /60# Converte a duração para horasdf_netflix2['duration h'] = pd.to_timedelta(df_netflix2['duration']).dt.total_seconds() / (60*60)# Converte a duração para diasdf_netflix2['duration d'] = pd.to_timedelta(df_netflix2['duration']).dt.total_seconds() / (24*60*60)# Tabela dos tipos de cada colunapd.DataFrame(df_netflix2.dtypes).rename(columns = {0: 'Tipo'})
Tipo
start time
datetime64[ns, Brazil/East]
profile name
object
duration
object
attributes
object
title
object
supplemental video type
object
device type
object
bookmark
object
latest bookmark
object
country
object
dias eng
object
dias pt
category
duration m
float64
duration h
float64
duration d
float64
Output 6: Tipos de objetos de cada coluna.
Observe no Output 7 que a variável start time indica 16 horas, 19 minutos e 51 segundos, o que corresponde a 3 horas a menos em relação ao Output 2. Isso ocorre porque o fuso horário Brazil/East tem uma diferença de exatamente 3 horas em relação ao UTC. Ao verificar a descrição da variável start time, é possível notar que os dados já estão no formato UTC. Em outras palavras, a conversão para UTC não era estritamente necessária (embora seja importante realizar essas etapas para garantir a consistência dos dados), e agora as informações estão apresentadas no fuso horário correto.
Code
# Primeira linha da basedf_netflix2.head(1)
start time
profile name
duration
attributes
title
supplemental video type
device type
bookmark
latest bookmark
country
dias eng
dias pt
duration m
duration h
duration d
0
2023-05-19 16:19:51-03:00
Mãe
00:27:35
Autoplayed: user action: User_Interaction;
Black Knight: Temporada 1: Episódio 4 (Episódi...
FILME OU SERIE
Samsung 2018 Kant-M2 UHD TV (1.5G) Smart TV
00:27:39
00:27:39
BR (Brazil)
Friday
Sexta-feira
27.583333
0.459722
0.019155
Output 7: Primeira linha da base de dados.
Considerando o tempo de duração de cada sessão, conforme informado pelas variáveis “duration”, o Output 8 apresenta algumas estatísticas descritivas. Observa-se que o tempo mínimo de duração encontrado na base de dados é de 0,016667 minutos, conforme indicado pela variável duration m. Esse valor pode ser explicado pelas vezes em que um filme ou série foi aberto, mas logo em seguida perdemos o interesse em assistir ou clicamos por acidente.
Para fins de análise, decidi considerar apenas as informações com duração mínima de 2 minutos. Essa escolha é arbitrária e baseada na minha percepção de que 2 minutos são suficientes para entender que a pessoa clicou no filme ou série com a intenção de assistir, e manteve um tempo razoável para, pelo menos, confirmar que não foi um clique acidental.
Assim, o número de observações da base de dados foi reduzida para 5.552.
Code
# Medidas descritivas básicas das variáveis numéricasdf_netflix2.describe()
duration m
duration h
duration d
count
7804.000000
7804.000000
7804.000000
mean
27.916718
0.465279
0.019387
std
27.681499
0.461358
0.019223
min
0.016667
0.000278
0.000012
25%
2.583333
0.043056
0.001794
50%
22.066667
0.367778
0.015324
75%
42.833333
0.713889
0.029745
max
184.166667
3.069444
0.127894
Output 8: Medidas descritivas das variáveis numéricas.
Extraindo informações de textos com expressões regulares (regex)
Retornando ao problema mencionado nas variáveis title e device type, é importante notar, conforme mostrado no Output 9, que a coluna title contém informações sobre o título do filme ou série, bem como a temporada e o episódio, quando aplicável. Essas informações precisarão ser separadas adequadamente para uma análise mais precisa. Além disso, a variável device type, que indica o dispositivo utilizado para acessar a Netflix, contém informações específicas sobre o dispositivo em questão. No entanto, podemos extrair informações mais relevantes, como se o acesso foi feito por meio de uma TV, computador (PC) ou celular, por exemplo. Essa extração pode facilitar a realização de uma análise mais eficiente dos dados.
Code
# Filtrando a base mantendo apenas os casos com 2 minutos ou mais de duração (5552, 15)df_netflix2 = df_netflix2[df_netflix2['duration m'] >=2]# Cria dataframe com a coluna dos 10 primeiros titulos na base de dadostitulodispositivo = ( pd.DataFrame(df_netflix2['title'].unique()). rename(columns = {0: '10 primeiros títulos da base'}). head(10))# Adiciona ao dataframe a lista de dispositivos únicos na base de dados utilizados para assistir filmes e sériestitulodispositivo['Todos os dispositivos únicos da base'] = df_netflix2['device type'].unique()# Cria objeto de estilo a partir do dataframestyler = titulodispositivo.style# Esconde os índices, pois, nesse caso, as linhas entre as colunas não correspondemstyler.hide(axis ="index")
10 primeiros títulos da base
Todos os dispositivos únicos da base
Black Knight: Temporada 1: Episódio 4 (Episódio 4)
Samsung 2018 Kant-M2 UHD TV (1.5G) Smart TV
Black Knight: Temporada 1: Episódio 3 (Episódio 3)
TCL 2K18 FHD UnionTV Smart TV
Black Knight: Temporada 1: Episódio 2 (Episódio 2)
Netflix Linux Firefox Other
Black Knight: Temporada 1: Episódio 1 (Episódio 1)
Firefox PC (Cadmium)
Vingança entre Assassinos
Android DefaultWidevineL3Phone Android Phone (motorola_Moto G (5))
Conta comigo
Android DefaultWidevineL3Phone Android Phone
Agente Infiltrado
Edge OSS - Windows (Cadmium)
Freaks - Um de Nós
Chrome PC (Cadmium)
The Last Kingdom: Seven Kings Must Die
DefaultWidevineAndroidPhone
Noé
Netflix Windows Mobile 8 Windows 8
Output 9: Os 10 primeiros títulos e todos os dispositivos únicos da base de dados.
Para separar corretamente as informações dessas variáveis, utilizei expressões regulares (regex). No caso da variável title, é possível observar que observações relacionadas a séries possuem um título seguido da temporada e do episódio, enquanto os filmes apresentam apenas o título. Com base nessa observação, criei uma nova coluna chamada identf tipo, na qual identifico se o conteúdo assistido naquela sessão é uma série ou um filme. Utilizando regex, verifiquei se o texto na variável title continha palavras como “temporada”, “season”, “episódio” ou “episode” (considerando também letras maiúsculas), classificando-o como série. Caso contrário, foi classificado como filme. Vale ressaltar que utilizei palavras em inglês para fazer essa classificação, pois meus pais assistem filmes e séries apenas em português, enquanto eu e meu irmão possuímos perfis em inglês e assistimos conteúdos nesse idioma. Dessa forma, os títulos também se diferenciam por idioma.
Em seguida, criei a coluna identf titulo utilizando o mesmo método, no qual a regra estabelecida foi que o título sempre ocorre antes das palavras “temporada”, “season”, “episódio” ou “episode” (também considerando letras maiúsculas). Além disso, criei a coluna identf temporada, que identifica a temporada (caso seja uma série) por meio da extração da informação relacionada às palavras “temporada” e o respectivo número. O mesmo foi feito para extrair os episódios e preencher a coluna identf episodio.
No caso da coluna de dispositivos, extraí as informações relevantes para a coluna identf device, identificando se o dispositivo utilizado era uma TV por meio da palavra “TV”. Para dispositivos móveis, como celulares, verifiquei as palavras “Android”, “Mobile” ou “Phone”. Quanto aos acessos feitos por computadores, identifiquei-os pelos nomes dos navegadores utilizados, como “Chrome”, “Firefox”, “Edge” ou “Linux”. No entanto, vale mencionar que existe um dispositivo chamado “Netflix Linux Firefox Other” que não possui uma indicação clara sobre o tipo de dispositivo. Portanto, ao identificar as palavras “Linux” e “Firefox” para classificar como computador, poderia gerar informações incorretas na base de dados. No entanto, observe que todos os dispositivos que podem ser identificados com certeza como computadores possuem a palavra “PC” em seus nomes (exceto o Edge). Além disso, a palavra “Cadmium” é comum a todos os computadores. Portanto, também a utilizei para identificar corretamente os dispositivos. Quanto ao dispositivo “Netflix Linux Firefox Other”, não foi atribuída nenhuma classificação devido à incerteza das informações apresentadas.
No Output 10, é possível visualizar a estrutura atualizada da base de dados, incluindo apenas as variáveis de interesse após as transformações realizadas.
Code
# Cria coluna que identifica se é filme ou série utilizando regexdf_netflix2['identf tipo'] = df_netflix2['title'].apply(lambda x: 'serie'if re.search(r'temporada|season|episódio|episode', x, flags = re.IGNORECASE) else'filme')# Cria coluna que identifica o título simplificado utilizando regexdf_netflix2['identf titulo'] = df_netflix2['title'].apply(lambda x: re.search(r'(.*?)\s?(?:temporada|season|episódio|episode)', x, flags = re.IGNORECASE).group(1).rstrip(':') if re.search(r'temporada|season|episódio|episode', x, flags = re.IGNORECASE) else x)# Cria coluna que identifica a temporada se for serie, e nan caso filme (usando regex)df_netflix2['identf temporada'] = df_netflix2.apply(lambda row: re.search(r'((?:temporada|Temporada|season|Season)\s\d+)', row['title'], flags = re.IGNORECASE).group(1) if row['identf tipo'] =='serie'and re.search(r'(?:temporada|Temporada|season|Season)\s(\d+)', row['title'], flags = re.IGNORECASE) else np.nan, axis =1)# Cria coluna que identifica o episódio se for serie, e nan caso filme (usando regex)df_netflix2['identf episodio'] = df_netflix2.apply(lambda row: re.search(r'(?:episódio|Episódio|episode|Episode)\s(\d+)', row['title'], flags = re.IGNORECASE).group(0) if row['identf tipo'] =='serie'and re.search(r'(?:episódio|Episódio|episode|Episode)\s(\d+)', row['title'], flags = re.IGNORECASE) else np.nan, axis =1)# Cria coluna que identifica o dispositivo usado para assistir (usando regex)df_netflix2['identf device'] = df_netflix2['device type'].apply(lambda x: 'tv'if re.search(r'TV', x, flags = re.IGNORECASE) else ('computador'if re.search(r'Edge|Cadmium|Chrome', x, flags = re.IGNORECASE) else ('celular'if re.search(r'Android|Mobile|Phone', x, flags = re.IGNORECASE) elseNone ) ))# Base de dados com apenas as variáveis de interessedf_netflix3 = df_netflix2.drop( ['attributes', 'supplemental video type', 'device type', 'duration', 'bookmark', 'latest bookmark', 'country', 'title', 'dias eng'], axis =1)# Print das 5 primeiras linhasdf_netflix3.head(5)
start time
profile name
dias pt
duration m
duration h
duration d
identf tipo
identf titulo
identf temporada
identf episodio
identf device
0
2023-05-19 16:19:51-03:00
Mãe
Sexta-feira
27.583333
0.459722
0.019155
serie
Black Knight
Temporada 1
Episódio 4
tv
1
2023-05-19 15:09:15-03:00
Mãe
Sexta-feira
44.750000
0.745833
0.031076
serie
Black Knight
Temporada 1
Episódio 3
tv
2
2023-05-19 14:39:51-03:00
Mãe
Sexta-feira
29.350000
0.489167
0.020382
serie
Black Knight
Temporada 1
Episódio 2
tv
3
2023-05-18 16:46:26-03:00
Mãe
Quinta-feira
13.116667
0.218611
0.009109
serie
Black Knight
Temporada 1
Episódio 2
tv
4
2023-05-17 16:35:06-03:00
Mãe
Quarta-feira
4.566667
0.076111
0.003171
serie
Black Knight
Temporada 1
Episódio 2
tv
Output 10: Primeiras cinco linhas da base de dados com as variáveis de interesse.
Análise exploratória dos dados (EDA)
No Output 11, é possível verificar o tempo de uso de cada perfil ao assistir filmes e séries na Netflix. Eu e meu irmão apresentamos um tempo de uso bastante similar, enquanto que meu pai não utiliza muito a plataforma de forma individual. É muito comum ele assistir filmes e séries junto com minha mãe, ou quando assiste sozinho, utiliza o perfil dela. Isso pode explicar o motivo de o perfil dela ter o maior tempo de uso registrado.
É importante observar que o perfil “Família” possui o menor tempo de uso. Isso ocorre porque, em geral, não costumamos nos reunir com frequência para assistir conteúdos juntos. Principalmente eu e meu irmão gostamos de nos concentrar e compreender cada detalhe da obra, além de discutir sobre ela posteriormente. Quando tentamos assistir todos juntos, certamente não é possível manter essa mesma imersão, principalmente porque meus pais detestam filmes e séries legendados ou sem legenda alguma, dando preferência a filmes dublados.
Levando esses fatores em consideração, o perfil “Família” não será mais considerado daqui em diante. Os dados abrangem o período de 2017 a 2023 e fica claro que o uso desse perfil não é significativo para fazer qualquer tipo de comparação.
Code
# Quantidade de dias assistindo Netflix para cada perfildiasperfil = (df_netflix3. groupby('profile name')[['duration h', 'duration d']].sum(). reset_index(). sort_values(by ='duration h', ascending =False). rename(columns = {'profile name': 'Perfil', 'duration h': 'Horas', 'duration d': 'Dias'}) )# Cria objeto de estilo a partir do dataframestyler = diasperfil.style# Formata o número de digitos da saída para 2 casas decimaisformat_digitos = {'Horas': '{:.2f}', 'Dias': '{:.2f}'}styler.format(format_digitos)# Esconde os índices, pois, nesse caso, o intuito é mostrar uma tabelastyler.hide(axis ="index")
Perfil
Horas
Dias
Mãe
1341.27
55.89
Eu
841.94
35.08
Irmão
812.68
33.86
Pai
618.74
25.78
Família
5.69
0.24
Output 11: Tempo em horas e dias de uso da Netflix de cada perfil.
O Output 12 sugere que, de maneira geral, todos na minha família assistem mais a séries do que filmes na Netflix, com exceção do meu pai, que parece preferir filmes em vez de séries. Essa preferência é evidente na realidade, pois ele não gosta de assistir algo sem um fim definido ou que demande muito tempo para ser concluído, permitindo-lhe dedicar-se a outras atividades diárias. Isso contrasta com as séries, que muitas vezes exigem várias horas ou até mesmo dias para serem finalizadas. É possível que uma parte significativa do tempo gasto assistindo aos filmes registrados no perfil da minha mãe seja resultado do meu pai assistindo sozinho ou assistindo em conjunto com ela.
Code
# Desconsidera o perfil 'Família'df_netflix3 = df_netflix3[~df_netflix3['profile name'].isin(['Família'])]# Agrupa os dados por duração considerando os perfis e tipo (filme ou série)profiledevicetipo_group = (df_netflix3. groupby(['profile name', 'identf tipo'])['duration h'].sum(). reset_index())pivot_profiledevicetipo = profiledevicetipo_group.pivot(index ='profile name', columns ='identf tipo', values ='duration h')# Traicing interativo das barras para cada tipo (filme ou série) e cria gráfico de barrasfig = go.Figure()for col in pivot_profiledevicetipo.columns: fig.add_trace(go.Bar( x = pivot_profiledevicetipo.index, y = pivot_profiledevicetipo[col], name = col, hovertemplate ='Horas: %{y:.2f}<br>' ))# Layout do gráficofig.update_layout( barmode ='stack', title ='Tempo (Horas) gasto assistindo filmes e séries em cada perfil', xaxis_title ='Perfis', yaxis_title ='Horas')fig.update_yaxes(tickformat ='h')# Plot do gráficofig.show()
Output 12: Consumo da Netflix de cada perfil por Filmes e Séries.
Quando se trata dos dispositivos de acesso, tanto eu quanto meu irmão passamos mais tempo utilizando a Netflix pelo computador. De acordo com o Output 13, isso é exatamente o que o gráfico sugere. Vale destacar que registrei um tempo considerável de 205 horas de uso da Netflix pelo celular. Isso se deve ao fato de que, durante o período em que os dados foram gerados (2017-2023), estive morando em outra cidade para estudar Estatística na faculdade. Nas férias, quando retorno à minha cidade natal, não tenho acesso a um computador e, portanto, costumo assistir à Netflix pelo celular, principalmente para assistir a animes.
No caso do perfil da minha mãe, a principal forma de acesso é por meio da TV, o que faz todo sentido, já que ela não usa computador. Sempre que ela utiliza a Netflix, é através da Smart TV. Por outro lado, é importante observar que o gráfico sugere que o computador é o dispositivo mais utilizado no perfil do meu pai. Isso não faz sentido, uma vez que ele também não usa computador. No entanto, é bastante comum que meu irmão acesse ocasionalmente os perfis tanto do meu pai quanto da minha mãe para dar sugestões de filmes e séries a pedido deles. Ele faz esse trabalho de acessar os perfis deles porque o perfil dele está configurado em inglês, e os filmes e séries que ele conhece podem ter nomes diferentes nos perfis dos meus pais. Esse detalhe pode ser uma possível explicação para o aparecimento do tempo de uso da Netflix pelo computador nos perfis dos meus pais. No entanto, é certo que as 213 horas de uso da Netflix pelo computador no perfil do meu pai não foram por ele.
Code
# Agrupa os dados por duração considerando os perfis e dispositivosprofiledevicehoras_group = (df_netflix3. groupby(['profile name', 'identf device'])['duration h'].sum(). reset_index())# Traicing interativo das barras para cada dispositivo único e cria gráfico de barrasfig = go.Figure()for device in profiledevicehoras_group['identf device'].unique(): device_data = profiledevicehoras_group[profiledevicehoras_group['identf device'] == device] fig.add_trace(go.Bar(x = device_data['profile name'], y = device_data['duration h'], name = device, hovertemplate ='Horas: %{y:.2f}<br>'))# Layout do gráficofig.update_layout(barmode ='group', title ='Tempo (Horas) de uso da Netflix em diferentes dispositivos em cada perfil', xaxis_title ='Perfis', yaxis_title ='Horas')fig.update_yaxes(tickformat ='h')# Plot do gráficofig.show()
Output 13: Consumo da Netflix de cada perfil por dispositivos.
O Output 14 sugere que o tempo dedicado ao uso da Netflix nos perfis dos meus pais é maior nos finais de semana, estendendo-se até segunda e terça-feira. Isso faz sentido, uma vez que eles precisam trabalhar durante a semana. Por outro lado, meu irmão apresenta uma distribuição de uso mais uniforme ao longo dos dias da semana. Curiosamente, eu percebo que meu tempo de uso da Netflix aumenta conforme me aproximo do final de semana, o que pode parecer um pouco estranho.
Code
# Agrupa os dados por duração considerando os perfis e os dias da semanaprofiledevicedias_group = (df_netflix3. groupby(['profile name', 'dias pt'])['duration h'].sum(). reset_index())# Traicing interativo das barras para cada dia da semana e cria gráfico de barrasfig = go.Figure()for device in profiledevicedias_group['dias pt'].unique(): device_data = profiledevicedias_group[profiledevicedias_group['dias pt'] == device] fig.add_trace(go.Bar(x = device_data['profile name'], y = device_data['duration h'], name = device, hovertemplate='Horas: %{y:.2f}<br>'))# Layout do gráficofig.update_layout(barmode ='group', title ='Tempo (Horas) de uso da Netflix ao longo dos dias da semana em cada perfil', xaxis_title ='Perfis', yaxis_title ='Horas')fig.update_yaxes(tickformat ='h')# Plot do gráficofig.show()
Output 14: Uso da Netflix de cada perfil por dias da semana.
Com o objetivo de descobrir quais são as séries mais assistidas, foi gerado o gráfico no Output 15. Logo de início, podemos perceber que o gráfico indica que a série mais visualizada no perfil do meu pai é “Supernatural”. Fiquei surpreso com a quantidade de horas dedicadas a essa série através do perfil dele, mas posso afirmar que boa parte desse tempo foi enquanto ela estava reproduzindo em segundo plano e ele realizava outras atividades, o que é bastante comum.
Além disso, o perfil da minha mãe apresenta um maior tempo de uso para as séries “Betty em Nova York”, “Lost” e “The 100”. Posso confirmar essas informações, pois presenciei diversas vezes ela assistindo a essas séries e, inclusive, tive boas conversas com ela sobre “Lost”. No perfil do meu irmão, houve um maior tempo de uso da Netflix assistindo à série “Vikings”, sendo que 36 horas também foram contabilizadas no perfil do meu pai.
Por fim, o meu perfil teve um tempo maior de visualização da série “Friends”. Essa não é necessariamente a minha série favorita, mas levando em consideração que ela possui 236 episódios, com uma média de 22 minutos cada, de acordo com o IMDb, o que totaliza aproximadamente 87 horas, faz todo sentido a informação apresentada no gráfico.
Code
# Agrupa os dados por perfil e por titulo e soma as horas assistidasprofile_title_duration = (df_netflix3[df_netflix3['identf tipo'] =='serie']. groupby(['profile name', 'identf titulo'])['duration h'].sum(). reset_index())# Sorteia os dados por perfil e por tempo assistido em forma decrescenteprofile_title_duration = profile_title_duration.sort_values(by = ['profile name', 'duration h'], ascending=[True, False])# As 5 séries mais assistidas de cada perfiltopfive = profile_title_duration.groupby('profile name').head(5)# Gráfico de barras interativo horizontal preenchido por perfilfig = px.bar(topfive, x ='duration h', y ='identf titulo', color ='profile name', orientation ='h', title ='As 5 séries mais assistidas de cada perfil (horas)')# Layout do gráficofig.update_layout(xaxis_title ='Horas assistidas', yaxis_title ='Nome da série')# Plot do gráficofig.show()
Output 15: As cinco séries mais assistidas de cada perfil.
Levando em conta apenas o meu perfil e a série que eu mais assisti na Netflix (Friends), o Output 16 sugere que eu começava a assistir os episódios por volta da hora do almoço (11 da manhã) e tinha uma maior frequência de visualização por volta da meia-noite (com destaque para as 23h). Considerando que houve uma época em que eu tinha um horário um pouco peculiar, em que dormia em momentos específicos do dia e ficava mais ativo após as 21h até o amanhecer, o comportamento desse gráfico começa a fazer um pouco mais de sentido (só para constar, atualmente não tenho mais esse horário).
Code
# Base de dados referente a mim com apenas a série Friendsdf_eu = df_netflix3[df_netflix3['profile name'] =='Eu']friends = df_eu[df_eu['identf titulo'].str.contains('Friends', regex =False)]# Atribui uma cópia da base até então para evitar warnings desnecessáriosfriends = friends.copy()# Cria coluna de horas do diafriends['horas'] = friends['start time'].dt.hour# Agrupa os dados por duração considerando as horas do diahoras_duracao = friends.groupby(['horas'])['identf episodio'].count().reset_index()# Traicing interativo das barras para cada hora do dia e cria gráfico de barrasfig = go.Figure()for hour in horas_duracao['horas'].unique(): hour_data = horas_duracao[horas_duracao['horas'] == hour] fig.add_trace(go.Bar(x = hour_data['horas'], y = hour_data['identf episodio'], name =str(hour), hovertemplate ='Episódios: %{y:.2f}<br>', showlegend =False))# Layout do gráficofig.update_layout(barmode ='group', title ='Número de episódios de Friends assistidos por mim em diferentes momentos do dia', xaxis_title ='Hora no dia do início da visualização', yaxis_title ='Número de episódios assistidos')fig.update_yaxes(tickformat ='h')fig.update_xaxes(tickmode ='array', tickvals = horas_duracao['horas'].unique(), ticktext = horas_duracao['horas'].unique())# Plot do gráficofig.show()
Output 16: Número de episódios de Friends assistidos por mim considerando o início em diferentas momentos do dia.
Para finalizar, o Output 17 sugere que quando eu começava a assistir Friends às quintas-feiras, eu assistia a mais episódios. No entanto, não consigo pensar em possíveis motivos para que isso ocorresse.
Code
# Agrupa os dados por dias da semana considerando o número de episódios assistidos de Friendsprofiledevicedias_group = (friends. groupby(['dias pt'])['identf episodio']. count(). reset_index())# Traicing interativo das barras para cada dia da semana e cria gráfico de barrasfig = go.Figure()for device in profiledevicedias_group['dias pt'].unique(): device_data = profiledevicedias_group[profiledevicedias_group['dias pt'] == device] fig.add_trace(go.Bar(x = device_data['dias pt'], y = device_data['identf episodio'], name = device, hovertemplate ='Número de episódios: %{y:.2f}<br>', showlegend =False))# Layout do gráficofig.update_layout(barmode ='group', title ='Número de episódios de Friends assistidos ao longo dos dias da semana', xaxis_title ='Dias da semana', yaxis_title ='Número de episódios')fig.update_yaxes(tickformat ='d')# Plot do gráficofig.show()
Output 17: Número de episódios de Friends assistidos por mim considerando o início em diferentas dias da semana.
Conclusão
Considerando que eu tenho familiaridade com o comportamento dos usuários dos perfis, naturalmente seria capaz de identificar se as análises fazem sentido ou não, além de oferecer possíveis explicações para certos resultados apresentados. Portanto, se os dados foram adequadamente tratados e limpos, com as informações extraídas de forma eficiente, relacionar os resultados com a realidade deveria ser uma tarefa simples para mim.
Ao longo do texto, pudemos observar que consegui estabelecer claramente a maioria dos gráficos (exceto o Output 17) e compreender se as informações apresentadas estavam coerentes. Isso demonstra que os dados estão bem organizados e fornecem informações relevantes, resultado de todo o processo que descrevi de limpeza e organização das informações, incluindo a manipulação de texto com o uso de expressões regulares.
Caso os dados não fossem adequadamente tratados, os resultados apresentados poderiam conter inconsistências e levar a conclusões equivocadas, especialmente se análises mais complexas, como testes estatísticos ou A/B, fossem necessárias. Esse é um problema que observei em muitas pessoas, e muitas vezes ocorre devido à negligência de procedimentos e etapas básicas, como as que mencionei anteriormente. É crucial garantir uma abordagem cuidadosa desde o tratamento inicial dos dados até a interpretação final dos resultados, a fim de obter conclusões confiáveis e evitar erros na análise.