Este caderno é um suplemento à aula sobre análise exploratória de dados. Irá demonstrar algumas funcionalidades da biblioteca Pandas que podem ser usadas em tarefas de análise.
A biblioteca Pandas é uma biblioteca de linguagem de programação Python usada para trabalhar com dados tabulares. É caracterizado por um grande número de funções que podem facilitar e acelerar o trabalho e fornecer informações úteis sobre o conjunto de dados. Para poder usar a biblioteca Pandas, primeiro precisamos carregá-la com o comando: import pandas as pd.
#%pip install pandas #uncomment if you need
import pandas as pd
Carregaremos também as restantes bibliotecas de que necessitaremos para o nosso trabalho.
import numpy as np
from matplotlib import pyplot as plt
Estruturas de séries e DataFrame
As estruturas de dados básicas usadas pela biblioteca Pandas são Series e DataFrame. Podemos pensar na estrutura DataFrame como uma estrutura tabular com recursos associados a linhas e colunas, enquanto a estrutura Series pode ser imaginada como uma única coluna desta tabela, com recursos associados a linhas.
A estrutura da série é criada usando a função de mesmo nome Series. A estrutura a seguir points_color contém informações sobre as cores dos pontos.
points_color = pd.Series(['red', 'blue', 'red', 'green'])
points_color

Como podemos ver, cada entrada é determinada pelo seu índice de linha.
A estrutura DataFrame também pode ser criada utilizando a função com o mesmo nome. O bloco de código seguinte cria um quadro de dados com pontos num plano, que contém os nomes dos pontos e as suas coordenadas.
points = pd.DataFrame({
'point_name': ['A', 'B', 'C', 'D'],
'x': [20, 11, 3, 27],
'y': [18, -4, 10, 2]
})
points

As entradas nessas estruturas são determinadas por índices de linha e índices de coluna. Isto permite-nos aceder e ler os seus valores. Uma das funções que podemos usar para este fim é a função loc, que recebe por parâmetro o índice de linha e índice de coluna separados por vírgulas.
points.loc[1, 'x']

Se for necessário ler os valores de uma única coluna, por exemplo, a que contém os nomes dos pontos, podemos fazê-lo especificando o nome da coluna entre parênteses retos, como no exemplo seguinte.
Se for necessário ler os valores de várias colunas, deve ser especificada uma lista com os nomes das colunas, também entre parênteses retos.
points['point_name']

Se for necessário ler o valor de uma linha, por exemplo, a que tem o índice 2, podemos fazê-lo utilizando a função iloc.
points.iloc[2]

Carregando o conjunto de dados
A biblioteca Pandas oferece suporte para trabalhar com muitos formatos, como CSV, JSON, HTML, Excel e outros. Para cada um desses formatos, há uma função correspondente para carregar dados: read_csv, read_json, read_html, read_excel. Como podemos notar, todos eles começam com o prefixo read_.
O conjunto de dados que usaremos neste exercício é conhecido como Titanic e contém informações sobre os passageiros do navio Titanic que naufragou no Oceano Atlântico em 1912 depois de atingir um iceberg. Este conjunto de dados pode ser descarregado a partir da plataforma Kaggle em https://www.kaggle.com/competitions/titanic/. A plataforma fornece duas partes desse conjunto de dados, titanic_train.csv e titanic_test.csv, a primeira para treinamento e a segunda para modelos de teste. É necessário fazer o download do primeiro conjunto de dados e transferi-lo para a plataforma Google Drive de acordo com as diretrizes nas instruções de uso do Google Drive. Encontra-se sob o mesmo nome na pasta sample_data.
Como os dados estão em formato CSV, usaremos a função read_csv para carregá-los.
data_path = '/titanic/train.csv'
data = pd.read_csv(data_path)
As informações sobre as dimensões do conjunto de dados, ou seja, o número de linhas e de colunas, podem ser obtidas através da função shape. O número de linhas corresponde ao número de instâncias (ou registos), enquanto o número de colunas corresponde ao número de atributos (ou variáveis).
data.shape

As primeiras linhas do conjunto de dados carregado podem ser obtidas através da função head. De igual modo, as últimas linhas podem ser obtidas utilizando a função tail. Ambas as funções podem receber, como argumento, o número de linhas a apresentar — por defeito, são mostradas cinco linhas.
data.head()

Análise de atributos
Uma visão geral rápida dos nomes e tipos de atributos pode ser obtida usando a função info. Esta função também imprimirá o número de valores não ausentes para cada atributo.
data.info()

Os atributos presentes no conjunto de dados são: identificador do passageiro (PassengerId), indicador de se o passageiro sobreviveu ou não ao naufrágio (Survived), classe do passageiro (Pclass), nome do passageiro (Name), sexo do passageiro (Sex), idade (Age), número de membros da família a bordo (SibSp), número de crianças ou pais a bordo (Parch), código do bilhete (Ticket), preço do bilhete (Fare), número da cabine (Cabine), e a estação onde o passageiro embarcou no navio (Embarked). Pode ler mais sobre o significado desses atributos na página da plataforma Kaggle.
Entre os atributos numéricos, vamos destacar um atributo e analisá-lo separadamente. Que seja o atributo Fare que representa o preço do bilhete. Informações adicionais sobre este atributo podem ser obtidas chamando a função describe - que nos informa sobre o valor mínimo e máximo do atributo, o valor médio e os valores de percentil.
data['Fare'].describe()

Na saída, a count o número de valores na coluna, mean do valor médio, std o desvio padrão e min e max os valores mínimo e máximo, respectivamente. As saídas 25%, 50% e 75% indicam os valores percentis. Assim, o percentil 50 é o valor abaixo do qual se situa metade de todos os valores. Esse valor também é conhecido como mediana. Do mesmo modo, o percentil 25 indica o valor abaixo do qual se situa um quarto de todos os valores e o percentil 75 o valor abaixo do qual se situam três quartos de todos os valores. Estes valores também são chamados de primeiro e terceiro quartis, enquanto a mediana também é referida como o segundo quartil. O objetivo de todos esses cálculos é dar-nos uma visão sobre a distribuição dos valores de atributos.
Uma visão geral dos valores dos atributos também é obtida através de histogramas.
data['Fare'].hist()
A partir destas análises, pode ser interessante verificar posteriormente entradas com um preço de 0.
data[data['Fare']==0].shape

data[data['Fare']==0].head()

Da mesma forma, pode ser interessante verificar posteriormente as entradas com os preços mais altos.
data[data['Fare']>200].shape

data[data['Fare']>200].head()

O preço médio do bilhete pode ser calculado usando a função média.
data['Fare'].mean()
Também destacaremos um atributo categórico. Por exemplo o género dos passageiros Sex. Para atributos deste tipo, geralmente estamos interessados no conjunto de valores possíveis e sua frequência. A função value_counts pode ajudar-nos, pois calcula o número de ocorrências para cada valor possível.
data['Sex'].value_counts()
É conveniente mostrar graficamente estatísticas relacionadas a variáveis categóricas.
statistics_by_gender = data['Sex'].value_counts()
plt.title('Passenger Statistics by Gender')
plt.bar(statistics_by_gender.index, statistics_by_gender.values, color='orange')
plt.show()

Valores em falta
Como podemos notar a partir da saída da função info, existem atributos com valores ausentes.
Um desses atributos é o atributo Embarked, que marca a estação onde o passageiro embarcou no navio. Como só faltam dois valores, é mais natural apagar as linhas em que aparecem. A função isna ajuda-nos a verificar se um valor está em falta, enquanto a exclusão de linha em si pode ser implementada usando a função drop.
data[data['Embarked'].isna()]

data.drop(index=[61, 829], inplace=True)
data.shape

Como podemos notar, agora temos duas linhas a menos no conjunto de dados. Ao fornecer o argumento index para a função drop, especificamos os índices das linhas a serem excluídas, enquanto com o argumento inplace, indicamos que queremos que essas instâncias sejam excluídas "no lugar". O comportamento padrão ao excluir é gerar uma cópia modificada dos dados.
Na coluna Cabine, vemos que faltam muitos valores - apenas 204 valores são conhecidos. Portanto, é mais conveniente excluir esta coluna completamente. Para esse efeito usa-se a função drop, mas desta vez especificando o nome da coluna em vez do índice.
data.drop(columns=['Cabin'], inplace=True)
data.shape

data.head()

A última coluna com valores em falta é a coluna Idade. A exclusão de linhas com valores ausentes para esse atributo resultaria na perda de cerca de um quinto do conjunto de dados, e a própria coluna tem mais valores conhecidos do que os ausentes. Por isso, é conveniente substituir os valores em falta, por exemplo, pela idade média dos passageiros. A função fillna, que espera que o valor substitua os valores ausentes como um argumento, pode ajudar com essa tarefa. Também realizamos essa substituição no local usando o argumento inplace.
average_age = data['Age'].mean()
data['Age'].fillna(average_age, inplace=True)
data['Age'].hist()

Duplicados
A presença de duplicados no conjunto de dados pode ser verificada usando a função duplicate. Esta função retornará True para cada linha repetida e False caso contrário.
duplicate = data.duplicated()
duplicate.value_counts()

Como podemos ver, todos os valores são False, então podemos concluir que não há dados duplicados.
Deteção de valores atípicos
A deteção de valores atípicos envolve examinar valores de atributos individuais e analisar mais profundamente aqueles que parecem suspeitos ou irrelevantes para o domínio. Vamos analisar melhor o atributo Idade.
Ao examinar os valores do atributo Age usando a função describe e apresentando graficamente com a função boxplot, notamos que existem alguns valores excepcionalmente pequenos e alguns valores maiores. Estas questões têm de ser analisadas.
data['Age'].describe()

data.boxplot(column=['Age'])

data[data['Age']<1]

Parece que havia crianças no navio com menos de um ano de idade (felizmente, todas sobreviveram!). Nos casos em que o identificador do passageiro é 470 e 645, parece que todos os dados se sobrepõem, exceto o nome. Esta pode ser uma duplicata potencial ou podem ser irmãs; É incomum que o número do bilhete seja o mesmo.
data[data['Age']>70]

Parece que entre os casos selecionados onde a idade é superior a 70 anos, não há valores incomuns.
Do mesmo modo, os restantes atributos devem ser analisados da mesma forma.
Correlação de atributos
Para avaliar a correlação de atributos no conjunto de dados, podemos usar a função corr. Por padrão, calcula o coeficiente de correlação de Pearson entre cada par de atributos. Antes de usar essa função, vamos selecionar os atributos cuja correlação queremos examinar. Que eles sejam Survived, Pclass, Sex, Age, SibSp, Parch, e Fare.
data.head()

data_restriction = data[['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare']].copy()
Como o atributo Sex é categórico, vamos mapear o valor masculino para 0 e o valor feminino para 1. A função mapa irá ajudar-nos nesta tarefa.
Como o atributo Sex é categórico, vamos mapear o valor male para 0 e o valor feminino para 1. A função map irá ajudar-nos nesta tarefa..
data_restriction['Sex'] = data_restriction['Sex'].map({'male': 0, 'female':1})
A função corr calcula os valores do coeficiente de correlação entre atributos.
corelation_matrix = data_restriction.corr()
corelation_matrix

Como discutimos, para facilitar a análise dos valores obtidos, a matriz de correlação também é apresentada na forma de um mapa de calor. A função show_corelations permite tal apresentação.
def show_corelations(podaci):
# calculate the correlation matrix
corelation_matrix = data.corr()
# prepare axis labels
atributes_number = podaci.columns.shape[0]
plt.xticks(np.arange(0, atributes_number), data.columns, rotation=45)
plt.yticks(np.arange(0, atributes_number), data.columns)
# prepare the heatmap
plt.imshow(corelation_matrix)
# display the color bar with paired colors and values it represents
plt.colorbar()
# display the prepared graph
plt.show()
show_corelations(data_restriction)

A partir desta matriz, podem ser tiradas conclusões tais como que quanto mais baixa a classe de passageiros, menor o preço do bilhete (quadrado roxo escuro no cruzamento da linha de Tarifa e coluna Pclass), que o sexo do passageiro correlaciona-se positivamente com a informação de se o passageiro sobreviveu (é útil saber que a evacuação de mulheres e crianças foi realizada), e outras informações.
- Make a submission
