Carregamento de Dados em Python: Leitura Eficiente de CSV, Excel e Bancos SQL

Objetivos de Aprendizagem

Ao concluir este tutorial, você será capaz de:

  • Usar o pandas para ler dados de arquivos de texto como CSV e TSV.
  • Ler arquivos Excel e gerenciar múltiplas planilhas.
  • Lidar com problemas comuns de codificação e formatos de dados anômalos.
  • Utilizar a leitura em partes (chunking) para processar arquivos maiores que a memória disponível.
  • Conectar-se a bancos de dados SQLite e MySQL para executar consultas.
  • Aplicar técnicas de otimização de desempenho na leitura de dados.

Introdução ao Pandas

O pandas é uma biblioteca fundamental para análise de dados em Python, construída sobre o NumPy. Suas duas estruturas de dados centrais são:

  • Series: Um array unidimensional com rótulos.
  • DataFrame: Uma tabela bidimensional, similar a uma planilha do Excel.
import pandas as pd
import numpy as np

# Exemplo de Series
notas = pd.Series([85, 92, 78, 96],
                  index=['Ana', 'Bruno', 'Carlos', 'Diana'],
                  name='Matemática')
print(notas)

# Exemplo de DataFrame
tabela_funcionarios = pd.DataFrame({
    'Nome': ['Ana', 'Bruno', 'Carlos', 'Diana'],
    'Departamento': ['TI', 'Marketing', 'Financeiro', 'TI'],
    'Salario': [15000, 12000, 13000, 18000]
})
print(tabela_funcionarios)

Leitura de Arquivos CSV

Leitura Básica

O formato CSV (valores separados por vírgula) é o formato de troca de dados mais comum.

# Criar um arquivo CSV de exemplo
dados_pedidos = {
    'PedidoID': range(1, 6),
    'Produto': ['Notebook', 'Monitor', 'Teclado', 'Mouse', 'Webcam'],
    'Preco': [3500, 1200, 250, 150, 300],
    'Quantidade': [1, 2, 3, 5, 2]
}
df_pedidos = pd.DataFrame(dados_pedidos)
df_pedidos.to_csv('exemplo_pedidos.csv', index=False, encoding='utf-8')

# Ler o arquivo CSV
df_lido = pd.read_csv('exemplo_pedidos.csv')
print(f"Formato dos dados: {df_lido.shape}")
print(df_lido.dtypes)

Parâmetros Comuns do read_csv

# Demonstração de parâmetros úteis
# Criar um CSV mais complexo
csv_complexo = """ID,Nome,Nota,Status
001,Lucas,85.5,Aprovado
002,Maria,,Pendente
003,João,92.0,Aprovado
004,Ana,abc,Reprovado"""

with open('dados_complexos.csv', 'w', encoding='utf-8') as f:
    f.write(csv_complexo)

# 1. Especificar nomes das colunas
print("1. Colunas renomeadas:")
df_custom = pd.read_csv('dados_complexos.csv',
                        names=['Identificador', 'Aluno', 'Pontuacao', 'Situacao'],
                        header=0)
print(df_custom)

# 2. Ler apenas colunas específicas
print("\n2. Apenas Nome e Nota:")
df_parcial = pd.read_csv('dados_complexos.csv', usecols=['Nome', 'Nota'])
print(df_parcial)

# 3. Lidar com valores faltantes
print("\n3. Análise de dados faltantes:")
df_completo = pd.read_csv('dados_complexos.csv', na_values=['', ' '])
print(df_completo.isna().sum())

# 4. Definir tipos de dados específicos
print("\n4. Tipos de dados definidos:")
df_tipado = pd.read_csv('exemplo_pedidos.csv',
                        dtype={'PedidoID': str, 'Produto': 'category'})
print(df_tipado.dtypes)

# 5. Ler apenas primeiras N linhas (para pré-visualização)
print("\n5. Primeiras 3 linhas:")
df_amostra = pd.read_csv('exemplo_pedidos.csv', nrows=3)
print(df_amostra)

Arquivos com Outros Delimitadores

# Arquivo TSV (separado por tabulação)
dados_tsv = "ID\tNome\tNota\n1\tLucas\t85\n2\tMaria\t92"
with open('dados.tsv', 'w', encoding='utf-8') as f:
    f.write(dados_tsv)

print("Leitura de TSV:")
df_tsv = pd.read_csv('dados.tsv', sep='\t')
print(df_tsv)

# Arquivo separado por ponto e vírgula (comum em locais europeus)
dados_ptv = "ID;Nome;Nota\n1;Lucas;85\n2;Maria;92"
with open('dados_ptv.csv', 'w', encoding='utf-8') as f:
    f.write(dados_ptv)

print("\nLeitura com delimitador ';':")
df_ptv = pd.read_csv('dados_ptv.csv', sep=';')
print(df_ptv)

Leitura de Arquivos Excel

Leitura Básica

# Criar um arquivo Excel de exemplo
df_vendas = pd.DataFrame({
    'Vendedor': ['Ana', 'Bruno', 'Carlos'],
    'Região': ['Norte', 'Sul', 'Leste'],
    'Vendas_Q1': [45000, 32000, 28000],
    'Vendas_Q2': [48000, 35000, 31000]
})
df_estoque = pd.DataFrame({
    'Produto': ['P1', 'P2', 'P3'],
    'Quantidade': [150, 230, 180],
    'Preco_Unitario': [50.0, 75.0, 30.0]
})

# Salvar em diferentes planilhas
with pd.ExcelWriter('dados_empresariais.xlsx', engine='openpyxl') as escritor:
    df_vendas.to_excel(escritor, sheet_name='Vendas', index=False)
    df_estoque.to_excel(escritor, sheet_name='Estoque', index=False)

# Ler uma planilha específica
print("Planilha de Vendas:")
df_vendas_lido = pd.read_excel('dados_empresariais.xlsx', sheet_name='Vendas')
print(df_vendas_lido)

# Listar todas as planilhas
arquivo_excel = pd.ExcelFile('dados_empresariais.xlsx')
print(f"\nPlanilhas disponíveis: {arquivo_excel.sheet_names}")

# Ler todas as planilhas
todas_planilhas = pd.read_excel('dados_empresariais.xlsx', sheet_name=None)
for nome, df in todas_planilhas.items():
    print(f"\n--- {nome} ---")
    print(df.head(2))

Resolvendo Problemas de Codificação

Erros de codificação são frequentes ao trabalhar com dados reais. O erro UnicodeDecodeError indica que o arquivo não está sendo lido com a codificação correta.

# Função para detectar e lidar com codificações
import chardet

def detectar_codificacao(caminho_arquivo):
    with open(caminho_arquivo, 'rb') as f:
        resultado = chardet.detect(f.read(10000))
    return resultado['encoding']

def ler_csv_seguro(caminho_arquivo):
    codificacoes_tentar = ['utf-8', 'utf-8-sig', 'latin-1', 'gbk']
    for cod in codificacoes_tentar:
        try:
            df = pd.read_csv(caminho_arquivo, encoding=cod)
            print(f"Arquivo lido com sucesso usando codificação: {cod}")
            return df
        except UnicodeDecodeError:
            continue
    raise ValueError("Não foi possível ler o arquivo com as codificações conhecidas.")

# Exemplo de uso
# codificacao_detectada = detectar_codificacao('meu_arquivo.csv')
# df = ler_csv_seguro('meu_arquivo.csv')

Leitura em Partes para Arquivos Grandes

Para arquivos que excedem a memória disponível, use o parâmetro chunksize para processar em partes.

# Criar um arquivo grande para demonstração
np.random.seed(42)
num_linhas = 50000
df_grande = pd.DataFrame({
    'ID': range(num_linhas),
    'Valor': np.random.normal(100, 25, num_linhas),
    'Categoria': np.random.choice(['Alpha', 'Beta', 'Gamma'], num_linhas)
})
df_grande.to_csv('arquivo_grande.csv', index=False)

# Processar em partes
tamanho_chunk = 10000
contagem_categorias = {}
soma_valores = 0.0
total_linhas = 0

for chunk in pd.read_csv('arquivo_grande.csv', chunksize=tamanho_chunk):
    # Contar categorias
    contagem = chunk['Categoria'].value_counts()
    for cat, cont in contagem.items():
        contagem_categorias[cat] = contagem_categorias.get(cat, 0) + cont
    
    # Somar valores
    soma_valores += chunk['Valor'].sum()
    total_linhas += len(chunk)
    print(f"Processadas {total_linhas} linhas...")

media_valores = soma_valores / total_linhas
print(f"\nProcessamento concluído:")
print(f"Total de linhas: {total_linhas:,}")
print(f"Média dos valores: {media_valores:.2f}")
print(f"Contagem por categoria: {contagem_categorias}")

Conexão com Bancos de Dados SQL

SQLite

import sqlite3

# Conectar e criar uma tabela de exemplo
conexao = sqlite3.connect('banco_empresa.db')
cursor = conexao.cursor()

# Criar tabela de funcionários
cursor.execute('''
    CREATE TABLE IF NOT EXISTS funcionarios (
        id INTEGER PRIMARY KEY,
        nome TEXT NOT NULL,
        departamento TEXT,
        salario REAL,
        data_contratacao TEXT
    )
''')

# Inserir dados
funcionarios = [
    (1, 'Ana Silva', 'TI', 7500.00, '2020-01-15'),
    (2, 'Bruno Costa', 'Marketing', 6000.00, '2021-03-10'),
    (3, 'Carlos Oliveira', 'TI', 8000.00, '2019-11-22'),
    (4, 'Diana Santos', 'Financeiro', 6500.00, '2022-06-05')
]
cursor.executemany('INSERT OR REPLACE INTO funcionarios VALUES (?, ?, ?, ?, ?)', funcionarios)
conexao.commit()

# Ler dados
print("Todos os funcionários:")
df_sql = pd.read_sql('SELECT * FROM funcionarios', conexao)
print(df_sql)

# Consulta com filtro
print("\nFuncionários de TI com salário > 7000:")
df_filtro = pd.read_sql(
    "SELECT nome, salario FROM funcionarios WHERE departamento = 'TI' AND salario > 7000",
    conexao
)
print(df_filtro)

# Consulta com agregação
print("\nEstatísticas por departamento:")
df_stats = pd.read_sql('''
    SELECT departamento, 
           COUNT(*) as num_funcionarios,
           AVG(salario) as salario_medio,
           MIN(salario) as salario_minimo
    FROM funcionarios 
    GROUP BY departamento
''', conexao)
print(df_stats)

conexao.close()

MySQL (Exemplo Conceitual)

# Nota: Este exemplo requer um servidor MySQL em execução e a instalação do pymysql.
# pip install pymysql sqlalchemy

"""
from sqlalchemy import create_engine

# String de conexão
url_conexao = 'mysql+pymysql://usuario:senha@localhost:3306/nome_banco'
motor = create_engine(url_conexao)

# Ler dados
df = pd.read_sql('SELECT * FROM tabela_clientes', motor)

# Escrever dados
df_novo.to_sql('tabela_backup', motor, if_exists='replace', index=False)

# Consulta complexa
df_relatorio = pd.read_sql('''
    SELECT c.nome, 
           SUM(v.valor) as total_vendas,
           COUNT(v.id) as num_pedidos
    FROM clientes c
    JOIN vendas v ON c.id = v.cliente_id
    GROUP BY c.id
    HAVING total_vendas > 10000
''', motor)
"""

Leitura de Outros Formatos

JSON

# Ler um arquivo JSON
import json

# Dados JSON de exemplo
dados_json = [
    {"produto": "A", "preco": 50, "vendas": 100},
    {"produto": "B", "preco": 75, "vendas": 80},
    {"produto": "C", "preco": 30, "vendas": 150}
]

with open('dados.json', 'w', encoding='utf-8') as f:
    json.dump(dados_json, f, ensure_ascii=False, indent=2)

# Carregar em DataFrame
df_json = pd.read_json('dados.json')
print(df_json)

HTML

# Extrair tabelas de páginas HTML
# Exemplo real: url = 'https://exemplo.com/tabela.html'
# tabelas = pd.read_html(url)

# Exemplo local
html_tabela = '''
<table>
    <tr><th>Nome</th><th>Idade</th></tr>
    <tr><td>Lucas</td><td>28</td></tr>
    <tr><td>Maria</td><td>32</td></tr>
</table>
'''

with open('tabela.html', 'w', encoding='utf-8') as f:
    f.write(html_tabela)

df_html = pd.read_html('tabela.html')[0]
print(df_html)

Exemplo Prático: Integração de Dados

# Cenário: Integrar dados de diferentes fontes

# Fonte 1: CSV com dados demográficos
demografia = pd.DataFrame({
    'cliente_id': [101, 102, 103, 104],
    'cidade': ['São Paulo', 'Rio de Janeiro', 'Belo Horizonte', 'Porto Alegre'],
    'faixa_etaria': ['25-34', '35-44', '25-34', '45-54']
})
demografia.to_csv('demografia.csv', index=False)

# Fonte 2: Excel com dados de compra
compras = pd.DataFrame({
    'cliente_id': [101, 102, 101, 103, 104, 102],
    'valor': [250, 180, 320, 410, 190, 275],
    'data': pd.date_range('2024-01-01', periods=6)
})
with pd.ExcelWriter('compras.xlsx', engine='openpyxl') as writer:
    compras.to_excel(writer, sheet_name='Compras', index=False)

# Fonte 3: Banco de dados com feedbacks
conexao = sqlite3.connect('feedback.db')
pd.DataFrame({
    'cliente_id': [101, 102, 103, 104],
    'avaliacao': [4.5, 3.8, 4.2, 4.7],
    'comentario': ['Ótimo produto', 'Bom atendimento', 'Entrega rápida', 'Excelente']
}).to_sql('feedbacks', conexao, if_exists='replace', index=False)

# Integrar os dados
df_demo = pd.read_csv('demografia.csv')
df_comp = pd.read_excel('compras.xlsx', sheet_name='Compras')
df_feed = pd.read_sql('SELECT * FROM feedbacks', conexao)

# Juntar todos os dados
df_completo = df_demo.merge(df_comp.groupby('cliente_id')['valor'].sum().reset_index(), on='cliente_id')
df_completo = df_completo.merge(df_feed, on='cliente_id')
df_completo.rename(columns={'valor': 'total_gasto'}, inplace=True)

print("Dados integrados:")
print(df_completo)

# Análise por cidade
analise_cidade = df_completo.groupby('cidade').agg({
    'total_gasto': ['mean', 'sum'],
    'avaliacao': 'mean',
    'cliente_id': 'count'
}).round(2)

print("\nAnálise por cidade:")
print(analise_cidade)

conexao.close()

Resumo das Técnicas

  • CSV: Use pd.read_csv() com atenção aos parâmetros sep, encoding, usecols e dtype.
  • Excel: Use pd.read_excel() especificando sheet_name. Instale o openpyxl.
  • Cdoificação: Enfrente erros de Unicode com encoding='utf-8-sig' ou 'latin-1'.
  • Arquivos Grandes: Utilize chunksize para processamento iterativo e eficiente em memória.
  • SQL: Use pd.read_sql() com consultas SQL específicas para otimizar a transferência de dados.
  • Performance: Sempre leia apenas as colunas necessárias (usecols) e defina os tipos de dados (dtype) apropriados.

Tags: pandas CSV Excel sqlite MySQL

Publicado em 6-19 19:36