Tutorial 3 - Matplotlib

Aprendendo a fazer gráficos

Carregando os pacotes

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

Lendo os dados

Você pode baixar os dados aqui.

imdb_filmes = pd.read_csv("pydata3/imdb_filmes.csv")
imdb_filmes.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 11340 entries, 0 to 11339
Data columns (total 20 columns):
 #   Column                Non-Null Count  Dtype  
---  ------                --------------  -----  
 0   id_filme              11340 non-null  object 
 1   titulo                11340 non-null  object 
 2   ano                   11339 non-null  float64
 3   data_lancamento       11340 non-null  object 
 4   generos               11340 non-null  object 
 5   duracao               11340 non-null  int64  
 6   pais                  11340 non-null  object 
 7   idioma                11261 non-null  object 
 8   orcamento             6389 non-null   float64
 9   receita               6366 non-null   float64
 10  receita_eua           5997 non-null   float64
 11  nota_imdb             11340 non-null  float64
 12  num_avaliacoes        11340 non-null  int64  
 13  direcao               11340 non-null  object 
 14  roteiro               11325 non-null  object 
 15  producao              11220 non-null  object 
 16  elenco                11336 non-null  object 
 17  descricao             11326 non-null  object 
 18  num_criticas_publico  11330 non-null  float64
 19  num_criticas_critica  11300 non-null  float64
dtypes: float64(7), int64(2), object(11)
memory usage: 1.7+ MB
imdb_filmes.describe()
ano duracao orcamento receita receita_eua nota_imdb num_avaliacoes num_criticas_publico num_criticas_critica
count 11339.000000 11340.000000 6.389000e+03 6.366000e+03 5.997000e+03 11340.000000 1.134000e+04 11330.000000 11300.000000
mean 1989.452244 99.691975 1.903052e+07 5.468264e+07 3.147534e+07 6.102487 3.591951e+04 138.221977 65.660885
std 25.548495 17.649559 3.238295e+07 1.433980e+08 6.033264e+07 1.128953 1.051027e+05 303.109281 85.890610
min 1914.000000 45.000000 0.000000e+00 1.600000e+01 2.520000e+02 1.300000 1.001000e+03 1.000000 1.000000
25% 1973.000000 89.000000 1.500000e+06 5.030680e+05 1.007583e+06 5.500000 1.877000e+03 31.000000 17.000000
50% 1997.000000 97.000000 6.500000e+06 9.521381e+06 1.067257e+07 6.300000 4.736500e+03 55.000000 35.000000
75% 2011.000000 108.000000 2.200000e+07 4.309351e+07 3.600150e+07 6.900000 2.106250e+04 127.000000 78.000000
max 2020.000000 271.000000 3.560000e+08 2.797801e+09 9.366622e+08 9.300000 2.278845e+06 8869.000000 909.000000
imdb_filmes.sample(8)
id_filme titulo ano data_lancamento generos duracao pais idioma orcamento receita receita_eua nota_imdb num_avaliacoes direcao roteiro producao elenco descricao num_criticas_publico num_criticas_critica
4965 tt0048260 Kismet 1955.0 1955-12-23 Adventure, Musical, Fantasy 113 USA English 2692960.0 NaN NaN 6.3 1329 Vincente Minnelli, Stanley Donen Charles Lederer, Luther Davis Metro-Goldwyn-Mayer (MGM) Howard Keel, Ann Blyth, Dolores Gray, Vic Damo... A roguish poet is given the run of the schemin... 42.0 23.0
5526 tt0049552 Nightfall 1956.0 1958-06-20 Crime, Drama, Film-Noir 78 USA English, Spanish, Italian NaN NaN NaN 7.2 3204 Jacques Tourneur Stirling Silliphant, David Goodis Copa Productions Aldo Ray, Brian Keith, Anne Bancroft, Jocelyn ... Through a series of bizarre coincidences, an a... 51.0 39.0
6362 tt0041822 Rope of Sand 1949.0 1949-08-03 Adventure, Film-Noir 104 USA English, Afrikaans NaN NaN NaN 6.8 1196 William Dieterle Walter Doniger, John Paxton Wallis-Hazen Burt Lancaster, Paul Henreid, Claude Rains, Pe... A man abused by a sadistic mining company cop ... 21.0 13.0
4728 tt5179598 Billionaire Boys Club 2018.0 2018-07-17 Biography, Drama, Thriller 108 USA English 15000000.0 2713955.0 1349.0 5.6 10299 James Cox James Cox, Captain Mauzner Armory Films Ansel Elgort, Kevin Spacey, Taron Egerton, Emm... A group of wealthy boys in Los Angeles during ... 70.0 41.0
597 tt0029843 The Adventures of Robin Hood 1938.0 1939-01-26 Action, Adventure, Romance 102 USA English 1900000.0 NaN NaN 7.9 46382 Michael Curtiz, William Keighley Norman Reilly Raine, Seton I. Miller Warner Bros. Errol Flynn, Olivia de Havilland, Basil Rathbo... When Prince John and the Norman Lords begin op... 279.0 107.0
914 tt0093800 Psychos in Love 1987.0 1987-05-01 Comedy, Horror 88 USA English 75000.0 NaN NaN 5.9 1071 Gorman Bechard Gorman Bechard, Carmine Capobianco Beyond Infinity Carmine Capobianco, Patti Chambers, Carla Brag... A strip-joint owner and a manicurist find that... 39.0 38.0
10697 tt0461770 Enchanted 2007.0 2007-12-07 Animation, Comedy, Family 107 USA English 85000000.0 340487652.0 127807262.0 7.0 173962 Kevin Lima Bill Kelly Walt Disney Pictures Amy Adams, Patrick Dempsey, James Marsden, Tim... A young maiden in a land called Andalasia, who... 421.0 231.0
5402 tt0096874 Back to the Future Part II 1989.0 1989-12-22 Adventure, Comedy, Sci-Fi 108 USA English 40000000.0 335973020.0 119000002.0 7.8 467662 Robert Zemeckis Robert Zemeckis, Bob Gale Universal Pictures Michael J. Fox, Christopher Lloyd, Lea Thompso... After visiting 2015, Marty McFly must repeat h... 421.0 149.0

Limpeza dos dados

Vamos converter a coluna data_lancamento para formato data.

# Get all unique non-date values from `data_lancamento`
non_date_values = imdb_filmes[pd.to_datetime(imdb_filmes['data_lancamento'], errors='coerce').isna()]['data_lancamento'].unique() 

if (len(non_date_values) > 20):
  # Sample 20 of them if there are too many unique values
  print(f"Non-date values in `data_lancamento`: {np.random.choice(non_date_values, 20, replace=False)}")
else:
  # Otherwise print all unique non-date values from `data_lancamento`
  print(f"Non-date values in `data_lancamento`: {non_date_values}")
Non-date values in `data_lancamento`: ['1989' '2010' '1990' '1970' '1974' '1967' '1973' '2006' '1971' '1983'
 '1966' '1999' '1956' '2005' '1927' '1948' '1943' '1961' '1997' '2009']
imdb_filmes['data_lancamento']=pd.to_datetime(imdb_filmes['data_lancamento'], format='%Y-%m-%d',
errors='coerce')

Tipos de visualizações

A visualização de dados é uma ferramenta poderosa que não só simplifica a compreensão de grandes volumes de dados, mas também desempenha um papel crucial na estatística aplicada e no aprendizado de máquina. Imagine o potencial de desbloquear insights valiosos e identificar padrões ocultos em seus conjuntos de dados! Com um conhecimento prévio do assunto, você pode explorar as nuances dos dados e revelar conexões significativas que podem surpreender e iluminar tanto você quanto sua audiência.

Gráfico de Dispersão

Quando há necessidade de encontrar correlações, são utilizados os gráficos de dispersão. Se existir um conjunto de dados XY, então um gráfico de dispersão é utilizado para encontrar a relação entre as variáveis X e Y.

As coordenadas x e y devem ser numéricas necessariamente. Vamos usar como exemplo, o dataframe imdb_filmes.

No exemplo, a posição do ponto no eixo x pode ser dada pela coluna orcamento e a posição do ponto no eixo y pela coluna receita.

plt.scatter(imdb_filmes['orcamento'], imdb_filmes['receita'])
plt.show()

Deixando o gráfico mais informativo:

plt.scatter(imdb_filmes['orcamento'], imdb_filmes['receita'],color='darkred',alpha=0.2)
plt.title('Gráfico de Dispersão entre Orçamento x Receita')
plt.xlabel('Orçamento')
plt.ylabel('Receita')
plt.show()

Gráfico de Barras

Um gráfico de barras também exibe tendências ao longo do tempo. No caso de múltiplas variáveis, um gráfico de barras pode facilitar a comparação dos dados para cada variável em todos os momentos no tempo. Por exemplo, um gráfico de barras pode ser utilizado para comparar o crescimento da empresa ano a ano.

Vamos usar o dataframe imdb_filmes para exemplificar, ordenando as linhas por ordem decrescente de nota_imdb. Primeiro vamos gerar o gráfico com as configuração padrão.

imdb_summary = imdb_filmes.sort_values('nota_imdb',
ascending=False).head(8)
plt.bar(imdb_summary['titulo'], imdb_summary['nota_imdb'])

Mas os nomes dos filmes estão sobrepostos, então neste caso é recomendável realizar um gráfico de barras horizontais.

plt.barh(imdb_summary['titulo'], imdb_summary['nota_imdb'])
plt.title('Top 10 Filmes por Nota IMDB')
plt.xlabel('Nota IMDB')
plt.show()

Gráfico de linha

Gráficos de linhas são utilizados para exibir tendências ao longo do tempo. O eixo X é geralmente utilizado para representar um período, enquanto o eixo Y é utilizado para representar a quantidade associada ao período de tempo no eixo X. Por exemplo, um gráfico de linhas pode ilustrar o horário de pico de visitas em um shopping durante o dia, dividido por dias da semana e horas.

Vamos fazer um gráfico utilizando a coluna data_lancamento

imdb_lancamento = imdb_filmes.groupby('data_lancamento').agg({'titulo':"count",'nota_imdb':'mean','duracao':'mean'})

imdb_lancamento.head()
titulo nota_imdb duracao
data_lancamento
1914-03-08 1 6.1 61.0
1914-08-24 1 6.4 78.0
1914-12-21 1 6.3 82.0
1915-03-21 1 6.3 195.0
1915-09-13 1 6.8 72.0
plt.plot(imdb_lancamento.index, imdb_lancamento['nota_imdb'])
plt.title('Tendência de notas imdb ao longo do tempo')
plt.xlabel('Data de Lançamento')
plt.ylabel('Nota IMDB')
plt.show()

é interessante porém, fica difícil de ver a tendência, vamos agrupar os filmes por ano e refazer o gráfico.

imdb_anual = imdb_filmes.groupby(pd.Grouper(key='data_lancamento', freq='Y'))['nota_imdb'].mean()

imdb_anual.head()
data_lancamento
1914-12-31    6.266667
1915-12-31    6.566667
1916-12-31    6.200000
1917-12-31    6.700000
1918-12-31    6.925000
Name: nota_imdb, dtype: float64
plt.plot(imdb_anual.index, imdb_anual.values)
plt.title('Tendência de notas imdb anuais ao longo do tempo')
plt.xlabel('Ano de Lançamento')
plt.ylabel('Nota Média IMDB')
plt.show()

Também podemos plotar duas ou mais linhas. Vamos calcular intervalo interquartil e inclui-la no gráfico anterior.

imdb_anual_25th = imdb_filmes.groupby(pd.Grouper(key='data_lancamento', freq='Y'))['nota_imdb'].quantile(0.25)
imdb_anual_75th = imdb_filmes.groupby(pd.Grouper(key='data_lancamento', freq='Y'))['nota_imdb'].quantile(0.75)
plt.plot(imdb_anual.index, imdb_anual.values,label='Média')
plt.plot(imdb_anual_25th.index, imdb_anual_25th.values,label='25 Percentil')
plt.plot(imdb_anual_75th.index, imdb_anual_75th.values,label='75 Percentil')
plt.title('Tendência de notas médias e IRQ do imdb anuais ao longo do tempo')
plt.xlabel('Ano de Lançamento')
plt.ylabel('Nota IMDB')
plt.legend()
plt.show()

Gráfico de Boxplot

Um gráfico de boxplot, também conhecido como diagrama de caixa, é uma ferramenta de visualização estatística que fornece uma representação compacta e informativa da distribuição de um conjunto de dados. Consiste em um retângulo (“caixa”) que se estende de um quartil ao outro, com uma linha vertical (ou “whisker”) estendendo-se de cada extremidade da caixa para representar a amplitude dos dados fora do intervalo interquartil.

imdb_filmes['ano'] = imdb_filmes['data_lancamento'].dt.year

imdb_filmes['decada'] = imdb_filmes['ano'] // 10 * 10

imdb_filmes['decada'].astype('category')

imdb_filmes.head()
id_filme titulo ano data_lancamento generos duracao pais idioma orcamento receita ... nota_imdb num_avaliacoes direcao roteiro producao elenco descricao num_criticas_publico num_criticas_critica decada
0 tt0092699 Broadcast News 1988.0 1988-04-01 Comedy, Drama, Romance 133 USA English, Spanish, French, German 20000000.0 67331309.0 ... 7.2 26257 James L. Brooks James L. Brooks Amercent Films William Hurt, Albert Brooks, Holly Hunter, Rob... Take two rival television reporters: one hands... 142.0 62.0 1980.0
1 tt0037931 Murder, He Says 1945.0 1945-06-23 Comedy, Crime, Mystery 91 USA English NaN NaN ... 7.1 1639 George Marshall Lou Breslow, Jack Moffitt Paramount Pictures Fred MacMurray, Helen Walker, Marjorie Main, J... A pollster stumbles on a family of murderous h... 35.0 10.0 1940.0
2 tt0183505 Me, Myself & Irene 2000.0 2000-09-08 Comedy 116 USA English, German 51000000.0 149270999.0 ... 6.6 219069 Bobby Farrelly, Peter Farrelly Peter Farrelly, Mike Cerrone Twentieth Century Fox Jim Carrey, Renée Zellweger, Anthony Anderson,... A nice-guy cop with Dissociative Identity Diso... 502.0 161.0 2000.0
3 tt0033945 Never Give a Sucker an Even Break 1947.0 1947-05-02 Comedy, Musical 71 USA English NaN NaN ... 7.2 2108 Edward F. Cline John T. Neville, Prescott Chaplin Universal Pictures W.C. Fields, Gloria Jean, Leon Errol, Billy Le... A filmmaker attempts to sell a surreal script ... 35.0 18.0 1940.0
4 tt0372122 Adam & Steve 2007.0 2007-05-17 Comedy, Drama, Music 99 USA English NaN 309404.0 ... 5.9 2953 Craig Chester Craig Chester Funny Boy Films Malcolm Gets, Cary Curran, Craig Chester, Park... Follows two New York city couples -- one heter... 48.0 15.0 2000.0

5 rows × 21 columns

data_to_plot = [imdb_filmes[imdb_filmes['decada'] == decada]['nota_imdb'] for decada in imdb_filmes['decada'].unique()]


plt.boxplot(data_to_plot, showmeans=True)
plt.show()

uma outra forma de plotar um Boxplot é utilizando a library seaborn

import seaborn as sns

sns.boxplot(x='decada', y='nota_imdb', data=imdb_filmes, showmeans=True)
plt.title('Distribuição de notas IMDB por Década')
plt.ylabel('IMDb Rating')
plt.show()

O gráfico ficou ruim de visualizar, porém, é possível alterar as dimensões de qualquer gráfico matplotlib, utilizando a opção: plt.figure(figsize=(15, 8)). Também podemos mudar a cor de cada caixa.

plt.figure(figsize=(15, 8))
sns.boxplot(x='decada', y='nota_imdb', hue='decada', data=imdb_filmes, showmeans=True)
plt.title('Distribuição de notas IMDB por Década')
plt.ylabel('IMDb Rating')
plt.show()

Gráfico de Histograma

Um histograma representa dados usando barras de alturas diferentes. Geralmente, cada barra agrupa números em intervalos em um histograma. Quanto mais alta as barras, mais dados se encaixam nesse intervalo. É usado para exibir a forma e a dispersão de amostras de um conjunto de dados contínuos. Por exemplo, podemos usar um histograma para medir as frequências de resposta da variável nota_imdb .

O Histograma serve para observar a distribuição dos dados e eventualmente serve para comparar mais de uma distribuição.

plt.hist(imdb_filmes['nota_imdb'], color='darkred', bins=30, edgecolor='black')
plt.xlabel('Nota IMDb')
plt.show()

também podemos utilizar seaborn para criar um histograma:

sns.histplot(data=imdb_filmes, x='nota_imdb', 
bins=30, color='darkblue')
plt.xlabel('Nota IMDb')
plt.show()

Gráfico de Pizza

imdb_filmes['lucro']=(imdb_filmes['receita']-imdb_filmes['orcamento']) > 0

lucratividade = imdb_filmes['lucro'].value_counts()
labels = ['Com Lucro', 'Sem Lucro']
sizes = lucratividade.values

plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=40)
plt.title('Proporção de filmes lucrativos e não lucrativos')
plt.axis('equal')
plt.show()

Podemos alterar as cores da nossa pizza utilizando cores = ['cor_1','cor_2',...,'cor_n'].

cores = ['#66b3ff','darkred']

plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=180, colors=cores)
plt.title('Proporção de filmes lucrativos e não lucrativos')
plt.axis('equal')
plt.show()

Mapas de Correlação

num_cols = imdb_filmes.select_dtypes(include=['int64', 'float64'])
corr_matrix = num_cols.corr()

sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')
plt.title('Heatmap de Correlações')
plt.show()