1
resposta

[Sugestão] Manipulando os dados - 07 Desafio: bora praticar?

import pandas as pd
import numpy as np  # Importação direta do NumPy
import matplotlib.pyplot as plt
import seaborn as sns
from urllib.request import urlopen
from urllib.parse import urlparse
import io
import csv
import logging
import os
from datetime import datetime

logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

def carregar_dados(url):
    ext = urlparse(url).path.split('.')[-1].lower()
    conteudo = urlopen(url).read()
    buffer = io.BytesIO(conteudo)
    if ext == 'csv':
        try:
            sep = csv.Sniffer().sniff(conteudo[:1024].decode('utf-8', errors='ignore')).delimiter
        except Exception:
            sep = ','
        try:
            return pd.read_csv(buffer, sep=sep, encoding='utf-8')
        except UnicodeDecodeError:
            buffer.seek(0)
            return pd.read_csv(buffer, sep=sep, encoding='latin1')
    elif ext in ('xls', 'xlsx'):
        return pd.read_excel(buffer)
    elif ext == 'json':
        return pd.read_json(buffer)
    else:
        raise ValueError(f'Extensão não suportada: .{ext}')

def criar_pasta_saida(base='output'):
    path = os.path.join(base, datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))
    os.makedirs(path, exist_ok=True)
    return path

# Carrega dados
url = 'https://raw.githubusercontent.com/alura-cursos/pandas-conhecendo-a-biblioteca/main/desafios/alunos.csv'
dados = carregar_dados(url)

if 'Notas' not in dados.columns:
    raise ValueError("Coluna 'Notas' não encontrada nos dados.")

dados['Notas'] = pd.to_numeric(dados['Notas'], errors='coerce')

# Calcula atividade extra, nota final e classifica
dados['Atv_Extra'] = dados['Notas'].apply(lambda x: x*0.4 if pd.notna(x) and x < 6 else 0)
dados['Nota_Final'] = dados['Notas'] + dados['Atv_Extra']

conds = [
    dados['Notas'].isna(),
    (dados['Nota_Final'] >= 6) & (dados['Atv_Extra'] == 0),
    (dados['Nota_Final'] >= 6) & (dados['Atv_Extra'] > 0),
    (dados['Nota_Final'] < 6) & (dados['Atv_Extra'] == 0),
    (dados['Nota_Final'] < 6) & (dados['Atv_Extra'] > 0),
]

valores = [
    'Dados Invalidos',
    'Aprovados Sem Atv_Extra',
    'Aprovados Com Atv_Extra',
    'Reprovados Sem Atv_Extra',
    'Reprovados Com Atv_Extra',
]

dados['Classificacao'] = pd.Series(
    pd.Categorical(
        np.select(conds, valores, default='Dados Invalidos'),
        categories=valores,
        ordered=True
    )
)

# Garante que Classificacao é última coluna
dados = dados[[c for c in dados.columns if c != 'Classificacao'] + ['Classificacao']]

# Resumo para gráfico
contagem = dados['Classificacao'].value_counts().reindex(valores).reset_index()
contagem.columns = ['Classificacao', 'Quantidade']
contagem['Porcentagem'] = 100 * contagem['Quantidade'] / contagem['Quantidade'].sum()

# Plot
plt.figure(figsize=(10,6))
cores = sns.color_palette('Set2', len(contagem))
bars = plt.bar(contagem['Classificacao'], contagem['Porcentagem'], color=cores)
for bar, pct, qtd in zip(bars, contagem['Porcentagem'], contagem['Quantidade']):
    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5,
             f'{pct:.1f}%\n({qtd})', ha='center', va='bottom', fontsize=10, fontweight='bold')
plt.xlabel('Classificação')
plt.ylabel('Porcentagem')
plt.title('Distribuição de alunos por classificação')
plt.xticks(rotation=45)
plt.ylim(0, contagem['Porcentagem'].max() + 10)
plt.tight_layout()
plt.show()

# Salvar arquivos
pasta_saida = criar_pasta_saida()
plt.savefig(os.path.join(pasta_saida, 'grafico.png'))
plt.close()
dados.to_csv(os.path.join(pasta_saida, 'alunos_processados.csv'), index=False)
contagem.to_csv(os.path.join(pasta_saida, 'resumo_classificacao.csv'), index=False)

# Salvar grupos
grupos = {
    'aprovados_sem_atividade_extra.csv': dados[dados['Classificacao'] == 'Aprovados Sem Atv_Extra'],
    'aprovados_com_atividade_extra.csv': dados[dados['Classificacao'] == 'Aprovados Com Atv_Extra'],
    'reprovados_sem_atividade_extra.csv': dados[dados['Classificacao'] == 'Reprovados Sem Atv_Extra'],
    'reprovados_com_atividade_extra.csv': dados[dados['Classificacao'] == 'Reprovados Com Atv_Extra'],
    'dados_invalidos.csv': dados[dados['Classificacao'] == 'Dados Invalidos'],
}
for nome, df in grupos.items():
    df.to_csv(os.path.join(pasta_saida, nome), index=False)

# Impressão final no console
print("\n=== Dados Processados (preview) ===")
print(dados.head(10))
print("\n=== Resumo de Classificação ===")
print(contagem)
print("\n=== Quantidade por Grupo ===")
for nome, df in grupos.items():
    print(f"{nome}: {len(df)} registros")

logging.info(f'Dados processados e salvos em: {pasta_saida}')
1 resposta

Oi, Marinaldo! Como vai?

Agradeço por compartilhar seu código com a comunidade Alura.

Seu script está bem estruturado, com atenção à leitura dinâmica de diferentes extensões de arquivos e tratamento robusto dos dados. A criação automatizada da pasta de saída também mostra um ótimo cuidado com a organização do projeto.

Uma dica interessante para o futuro é usar o método fillna() para tratar valores nulos diretamente em colunas numéricas, facilitando análises iniciais:


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

Esse código substitui os valores nulos por 0 na coluna Notas.

Qualquer dúvida que surgir, compartilhe no fórum.

Abraços e bons estudos!

Alura

Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!