Skip to content

Exploring some features of pandas in handling and cleaning data from a series of dataframes.

Notifications You must be signed in to change notification settings

paulocaldeiraa/tratamento-dados

Repository files navigation

banner

Python Jupyter Pandas Numpy Excel GitHub

📜 Índice

⁉️ Problematização

Imagina que você trabalha para uma empresa que está desenvolvendo um sistema para um dos setores. Nesse setor, existem muitas planilhas e os funcionários estão tendo dificuldade em organizar e manter as informações.

A equipe de TI entra em ação e arquiteta um programa para automatizar essa demanda. Seu trabalho é preparar todas as planilhas bagunçadas, gerar novas em formato CSV contendo apenas as informações mais relevantes, seguindo o modelo de dados desenhado. Isso irá garantir uma importação segura e organizada dos dados para o sistema novo.

Tendo em mente a situação simulada acima a ideia do projeto é explorar a biblioteca Pandas do Python, testando as múltiplas opções e observando os resultados. Também vou utilizar UUID que gera ID's aleatórios e o FAKER que cria dados falsos. Assim o projeto tem como objetivo servir de guia, principalmente para alguns dos recursos do Pandas, podendo ser consultado sempre que achar necessidade.

🐼 Pandas

O Pandas é uma ferramenta rápida, poderosa, flexível e fácil de usar, de análise e manipulação de dados. Essa biblioteca é de código aberto e foi construída em cima da linguagem de programação Python. Você pode conferir toda a documentação clicando aqui.

pd.apply

SINTAXE: DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwargs)

O método apply aplica uma função ao longo dataframe. Essa aplicabilidade pode ser definida pelo index (axis=0), ou pela coluna (axis=1). O retorno do apply vai ser o que for especificado pela função que ele vai aplicar no dataframe.

Um exemplo bem simples de como usar apply:

def alt_caractere(caractere):
    caractere = caractere.replace('a','b')
    return caractere

df = pd.DataFrame(
    {'col_1': [1],
    'col_2': ['a']}
)

df.apply(alt_caractere)

# Resultado:
    col_1 col_2
0    1    b

Na documentação em inglês você encontra mais detalhes e exemplos. Só clicar aqui.

pd.drop

SINTAXE: DataFrame.drop(labels=None, *, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')

O drop é utilizado para excluir linhas ou colunas do dataframe. Precisamos passar o nome correspondente ou indicar o index que deve ser removido. Existem outros métodos para excluir linhas ou colunas e estes são específicos como:

  • drop_duplicates: remove os duplicados
  • dropna: remove valores missing (faltantes)

Ao longo do projeto vou detalhar e exemplificar melhor cada uma. A documentação do drop é essa aqui. Você também pode ver um simples exemplo de como utiliza-lo.

df = pd.DataFrame(
    {'col_1': [1],
    'col_2': ['a']}
)
# Caso queira apagar a coluna 2, podemos usar o 'columns' que recebe o nome da coluna 
df.drop(columns='col_2')

# Resultado 
    col_1
0    1

# Podemos também passar o index da coluna e obter o mesmo resultado
df.drop('col_2', axis=1)

# Resultado 
    col_1
0    1

pd.fillna

SINTAXE: DataFrame.fillna(value=None, *, method=None, axis=None, inplace=False, limit=None, downcast=None)

O fillna preenche um valor missing no dataframe. Esse método pode parecer simples mas ele é muito útil quando estamos lidando com uma grande quantidade de dados. Um dos parâmetros que fillna recebe é 'method' que por padrão vem como None, mas podemos passar por exemplo 'ffill' que faz com que, pegue o último valor válido e preencha a próxima célula missing com ele. Vou detalhar esse método quando estiver trabalhando com ele no projeto. Por agora você pode conferir a documentação oficial.

pd.insert

SINTAXE: DataFrame.insert(loc, column, value, allow_duplicates=_NoDefault.no_default)

Com o insert você insere uma coluna nova no dataframe no local especificado. Basicamente você diz ao pandas, em qual posição quer a coluna, o nome da coluna e os valores. Você também encontra a documentação aqui.

df = pd.DataFrame(
    {'col_1': [1],
    'col_2': ['a']}
)

df.insert(1, 'col_3', 'abc')

# Resultado
    col_1 col_3 col_2
0   1     abc   a

# Se eu quisesse a col_3 no final, bastava mudar o parâmetro loc
df.insert(2, 'col_3', 'abc')

# Resultado
    col_1 col_2 col_3
0   1     a     abc

pd.melt

SINTAXE: pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None, ignore_index=True)

O melt reformula o dataframe, ele muda a orientação saindo de um formato amplo para um longo. Usamos melt quando queremos plotar cada item e analisar como estão distribuídos os valores. Ele retorna um dataFrame transformado que contém uma ou mais colunas identificadoras e apenas duas colunas não-identificadoras nomeadas variável e valor. Vou utilizar um exemplo que encontrei no site DelftStack.

# Criamos um df com 3 colunas 

dataframe=pd.DataFrame({'Attendance': {0: 60, 1: 100, 2: 80,3: 78,4: 95},
                    'Name': {0: 'Olivia', 1: 'John', 2: 'Laura',3: 'Ben',4: 'Kevin'},
                    'Obtained Marks': {0: '90%', 1: '75%', 2: '82%',3: '64%',4: '45%'}})

# Usando o método e identificando apenas a coluna 'Name'
# Como resultado vamos ter o agrupamento dos nomes e as duas colunas não-identificadoras

dataframe1 = pd.melt(dataframe, 
                     id_vars=['Name'])

# Resultado
     Name        variable value
0  Olivia      Attendance    60
1    John      Attendance   100
2   Laura      Attendance    80
3     Ben      Attendance    78
4   Kevin      Attendance    95
5  Olivia  Obtained Marks   90%
6    John  Obtained Marks   75%
7   Laura  Obtained Marks   82%
8     Ben  Obtained Marks   64%
9   Kevin  Obtained Marks   45%

Confira a documentação oficial do método.

pd.merge

SINTAXE: DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)

Com o merge é possível unir dois dataframes por coluna ou por index. Caso queira unir por coluna, o index de ambos os dataframes serão ignorados. O merge é bastante utilizado nesse projeto porque permite, de forma muito similar, fazer a função 'xlookup' do Excel. Como vamos trabalhar com varias planilhas as vezes em uma, consta algumas informações que não tem em outra, o merge conseguir unir e resolver esse problema. Vou deixar a documentação oficial e exemplificar melhor ao longo do trabalho.

pd.replace

SINTAXE: DataFrame.replace(to_replace=None, value=_NoDefault.no_default, *, inplace=False, limit=None, regex=False, method=_NoDefault.no_default)

Replace é um método muito útil para lidar com string (textos), é usado para substituir palavras ou trechos. Vou utilizar em diversas partes do projeto para remover ou alterar strings das tabelas. Um exemplo para limpar o dataframe é utilizar o replace para remover caracteres indesejados.

df = pd.DataFrame(
    {'col_1': [1,2,3,4],
    'col_2': ['a','b','c','d']}
)

df.replace('a',1)

# Resultado
    col_1	col_2
0	    1	1
1	    2	b
2	    3	c
3	    4	d

# Ou podemos passas mais de um valor em um dicionário
df.replace({'a':1, 'b':2})

# Resultado
    col_1	col_2
0	    1	1
1	    2	2
2	    3	c
3	    4	d

Vamos ver mais exemplos do replace durante o projeto. Você pode consultar a documentação oficial aqui.

pd.shift

SINTAXE: DataFrame.shift(periods=1, freq=None, axis=0, fill_value=_NoDefault.no_default)

O shift é usado para deslocar o index do dataframe. Ele recebe o parâmetro 'periods' que determina a quantidade de linhas que vão se deslocar, de cima para baixo. Enquanto desloca a novas linhas recebem NaN (valor missing) por padrão.

df = pd.DataFrame(
    {'col_1': [1,2,3,4],
    'col_2': ['a','b','c','d']}
)

df.shift(periods=1)

# Resultado
	col_1	col_2
0	NaN	    NaN
1	1.0	    a
2	2.0	    b
3	3.0	    c


Se caso eu quisesse inverter a ordem e deslocar de baixo para cima bastava alterar o parâmetro 'periods' para -1 (df.shift(periods=-1)). Também é possível deslocar colunas inteiras usando o parâmetro 'axis' como no exemplo, vamos usar o mesmo dataframe.

df.shift(periods=1, axis=1)

# Resultado
    col_1	col_2
0	NaN	    1
1	NaN	    2
2	NaN	    3
3	NaN	    4   

Perceba que agora o eixo se desloca da esquerda para a direita, se quiser alterar essa ordem, é so mudar novamente o parâmetro 'periods' para -1. Confira a documentação oficial do pandas.

pd.stack e pd.unstack

SINTAXE: DataFrame.stack(level=- 1, dropna=True)

SINTAXE: DataFrame.unstack(level=- 1, fill_value=None)

O stack e o unstack do Pandas fazem a rotação das colunas para as linhas e vice-versa. Tanto o stack quanto o unstack são usados para remodelar os dataframes, são adequados quando estamos lidando com tabelas de muilti-index. No stack obtemos como resultado a transformação da coluna de interesse em um index. Já no unstack faz exatamente o oposto, retomando o dataframe. Tabelas muilti-index são mais complexas do que as convencionais, no projeto vou abordar com mais detalhes e exemplificando esses dois métodos do pandas. Aqui você pode encontrar a documentação oficial do stack e aqui a documentação oficial do unstack

pd.to_datetime

SINTAXE: pandas.to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False, utc=None, format=None, exact=True, unit=None, infer_datetime_format=False, origin='unix', cache=True)

Esse método converte uma série em um objeto do tipo pandas datetime. É ideal para trabalhar com datas nas tabelas e evitar erros na hora de fazer importação, definindo o formato correto do banco de dados. Também é bastante útil quando as datas estão guardadas como string ou não são reconhecidas como data. Vou deixar para exemplificar o to_datetime ao longo do projeto, agora você pode conferir a documentação e alguns exemplos no site do pandas.

🔑 UUID

O UUID gera ID's únicos e imutáveis e essa biblioteca será muito valiosa no processo. Para o projeto temos muitas planilhas e cada linha de cada planilha e pode ser referente a um único dado. Atribuindo esse ID único gerado, garante que na hora da importação todas as informações serão direcionadas para cada ID. O UUDI é uma biblioteca que não vem inclusa no pacote do Anaconda, por exemplo. Talvez haja a necessidade de instalar e para isso pasta digitar o comando no terminal:

NOTA: pip install uuid

A geração dos ID's podem ocorrem de algumas formas, como queremos que cada um seja único a documentação oficial recomenda que usamos o uuid4(). Assim, vou criar uma função no python que vai gerar o ID sempre que for preciso.

Os ID's gerados pelo UUID são como no exemplo:

import uuid 

uuid.uuid4()

# Resultado
UUID('ceb0da33-dbca-472d-bee1-4e0680356af6')

🤡 Faker

O faker gera dados falsos aleatórios para popular o dataframe. Vou utilizar pra preencher todas as planilhas, criando nomes, documentos, email e tudo mais que for necessário. Faker é uma biblioteca bastante fácil e intuitiva de usar. Assim como UUID é necessário fazer a instalação desse pacote.

NOTA: pip install faker

Vou deixar um exemplo aqui da utilização do faker e indicar a documentação oficial para mais detalhes.

from faker import Faker 
fake = Faker()

fake.name()

#Resultado 
'Brenda Duran'

fake.address()

#Resultado
'740 Ana Club Suite 945\nWest Edgarfort, WV 26740'