Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

1
resposta

(22. Python: Pandas: conhecendo a biblioteca) Desafio: bora praticar?

import pandas as pd

url = 'https://raw.githubusercontent.com/alura-cursos/pandas-conhecendo-a-biblioteca/main/desafios/alunos.csv'

dados = pd.read_csv(url, sep=',')

# Com base nisso, solucione os problemas propostos abaixo utilizando os conhecimentos adquiridos até aqui.

# 1) Verifique se a base de dados possui dados nulos e, caso tenha, realize o tratamento desses dados nulos da forma que achar mais coerente com a situação.

dados.isnull().sum()

dados['Notas'] = dados['Notas'].fillna(0)

dados.isnull().sum()

# 2) Os alunos "Alice" e "Carlos", não fazem mais parte da turma. Sendo assim, remova-os da base de dados.

dados.query('Nome == "Alice" | Nome == "Carlos"')

registros_remover = dados.query('Nome == "Alice" | Nome == "Carlos"').index
dados.drop(registros_remover, axis=0, inplace=True)

dados.query('Nome == "Alice" | Nome == "Carlos"')

# 3) Aplique um filtro que selecione apenas os alunos que foram aprovados.

dados

alunos_aprovados = dados[dados['Notas'] >= 7]

alunos_aprovados

# 4) Salve o DataFrame que possui apenas os alunos aprovados em um arquivo csv chamado "alunos_aprovados.csv".

alunos_aprovados.to_csv('alunos_aprovados.csv', index=False, sep=';')

# Extra) Ao conferir as notas dos alunos aprovados, notamos que algumas notas estavam incorretas. As alunas que tiraram nota 7.0, na 
# verdade, tinham um ponto extra que não foi contabilizado. Sendo assim, substitua as notas 7.0 da base de dados por 8.0. Dica: pesquise pelo 
# método replace.

alunos_aprovados

alunos_aprovados['Notas'] = alunos_aprovados['Notas'].replace(7.0, 8.0)

alunos_aprovados
1 resposta

Olá, Eduardo. Como vai?

Parabéns pela excelente resolução do desafio! O seu código demonstra que você assimilou muito bem os conceitos de manipulação, tratamento e filtragem de dados utilizando a biblioteca Pandas.

A escolha de preencher as notas nulas com 0 através do fillna(0) foi bem coerente, assim como a estratégia de capturar os índices com .index para depois aplicar o .drop(). A filtragem condicional e a exportação para CSV também ficaram impecáveis.

Para agregar ainda mais valor ao seu projeto e expandir o seu domínio sobre o Pandas, quero compartilhar duas dicas de boas práticas e otimização baseadas nas soluções que você construiu:

1. Otimizando a remoção de registros com o método .isin()

No exercício 2, você utilizou o método .query() combinando os nomes com o operador | (OU). Essa abordagem funciona perfeitamente para dois nomes, mas imagine se você precisasse remover uma lista com 20 alunos? O texto do .query() ficaria gigantesco.

Uma alternativa mais elegante e escalável no Pandas é utilizar o método .isin() combinado com o operador de negação do til (~). Esse operador diz ao Pandas: "selecione tudo, exceto o que estiver nesta lista".

Veja como o código fica mais limpo:

# Criamos uma lista com os nomes a remover
remover = ['Alice', 'Carlos']

# O ~ filtra a base mantendo apenas quem NÃO está na lista
dados = dados[~dados['Nome'].isin(remover)]

Dessa forma, você elimina a necessidade de buscar os índices e aplicar o .drop(), realizando a filtragem e a remoção em uma única linha de código direcionada.


2. Evitando o SettingWithCopyWarning no exercício extra

No desafio extra, ao executar a linha alunos_aprovados['Notas'] = alunos_aprovados['Notas'].replace(7.0, 8.0), é muito provável que o ambiente (como o Jupyter Notebook) tenha exibido um aviso em vermelho chamado SettingWithCopyWarning.

Esse aviso acontece porque a variável alunos_aprovados nasceu de uma filtragem direta (dados[dados['Notas'] >= 7]). Para o Pandas, ela não é um DataFrame totalmente independente, mas sim uma "visão" (uma cópia vinculada) do DataFrame original dados. Quando você tenta modificar uma coluna dessa cópia, o Pandas avisa que isso pode gerar comportamentos inesperados.

Para evitar esse aviso e garantir que você está trabalhando com um objeto isolado na memória, a boa prática é utilizar o método .copy() logo após fazer o filtro. Veja a diferença:

# O .copy() garante que alunos_aprovados é um novo DataFrame independente
alunos_aprovados = dados[dados['Notas'] >= 7].copy()

# Agora você pode alterar as notas sem receber avisos do Pandas
alunos_aprovados['Notas'] = alunos_aprovados['Notas'].replace(7.0, 8.0)

Garantir essa independência de DataFrames impede bugs sutis em projetos maiores de Ciência de Dados.

Você foi muito bem em todas as etapas, inclusive na busca pelo método .replace() no desafio extra. Continue com esse ótimo ritmo de estudos!

Espero que possa ter lhe ajudado!