Python para análise de dados e machine learning

1. Introdução ao Ecossistema Python para Dados

1.1. Por que Python é a linguagem dominante em Data Science e ML

Python tornou-se a linguagem padrão para análise de dados e machine learning devido à sua sintaxe clara, vasto ecossistema de bibliotecas especializadas e forte comunidade de suporte. Diferente de linguagens como R ou MATLAB, Python oferece uma transição suave entre prototipagem rápida e implantação em produção, sendo adotada por empresas como Google, Netflix e Spotify.

1.2. Visão geral das principais bibliotecas

  • NumPy: Base para computação numérica eficiente com arrays multidimensionais
  • Pandas: Manipulação de dados tabulares com DataFrames
  • Matplotlib/Seaborn: Visualização estática e estatística
  • Scikit-learn: Algoritmos de ML prontos para uso

1.3. Configuração do ambiente

# Criando ambiente virtual com conda
conda create -n data_science python=3.10
conda activate data_science

# Instalação das bibliotecas essenciais
pip install numpy pandas matplotlib seaborn scikit-learn jupyter

2. Manipulação e Limpeza de Dados com Pandas

2.1. Importação e exploração inicial

import pandas as pd
import numpy as np

# Carregando dataset de exemplo
df = pd.read_csv('vendas.csv')
print(df.head())
print(df.info())
print(df.describe())

2.2. Tratamento de valores ausentes e outliers

# Verificando valores ausentes
print(df.isnull().sum())

# Estratégias de tratamento
df['preco'].fillna(df['preco'].median(), inplace=True)
df.dropna(subset=['categoria'], inplace=True)

# Identificando outliers com IQR
Q1 = df['quantidade'].quantile(0.25)
Q3 = df['quantidade'].quantile(0.75)
IQR = Q3 - Q1
limite_inferior = Q1 - 1.5 * IQR
limite_superior = Q3 + 1.5 * IQR
df = df[(df['quantidade'] >= limite_inferior) & (df['quantidade'] <= limite_superior)]

2.3. Transformações avançadas

# Agregações com groupby
vendas_por_categoria = df.groupby('categoria')['valor'].sum().reset_index()

# Merge de datasets
clientes = pd.read_csv('clientes.csv')
df_completo = pd.merge(df, clientes, on='id_cliente', how='left')

# Pivot table
pivot_mensal = df.pivot_table(values='valor', index='categoria', columns='mes', aggfunc='sum')

# Funções apply
df['faixa_preco'] = df['preco'].apply(lambda x: 'baixo' if x < 50 else ('medio' if x < 200 else 'alto'))

3. Análise Exploratória e Visualização de Dados

3.1. Estatísticas descritivas e correlações

import matplotlib.pyplot as plt
import seaborn as sns

# Estatísticas detalhadas
print(df.groupby('categoria').agg({'preco': ['mean', 'std', 'min', 'max'], 'quantidade': 'sum'}))

# Matriz de correlação
correlacao = df[['preco', 'quantidade', 'valor']].corr()
print(correlacao)

3.2. Gráficos essenciais

# Histograma
plt.figure(figsize=(10, 6))
plt.hist(df['preco'], bins=30, edgecolor='black', alpha=0.7)
plt.title('Distribuição de Preços')
plt.xlabel('Preço')
plt.ylabel('Frequência')
plt.show()

# Boxplot por categoria
plt.figure(figsize=(12, 6))
sns.boxplot(x='categoria', y='preco', data=df)
plt.title('Distribuição de Preços por Categoria')
plt.xticks(rotation=45)
plt.show()

# Scatterplot com correlação
plt.figure(figsize=(10, 6))
sns.scatterplot(x='preco', y='quantidade', hue='categoria', data=df, alpha=0.6)
plt.title('Relação entre Preço e Quantidade Vendida')
plt.show()

3.3. Identificação de padrões

# Pairplot para múltiplas variáveis
sns.pairplot(df[['preco', 'quantidade', 'valor', 'categoria']], hue='categoria')
plt.show()

# Heatmap de correlação
plt.figure(figsize=(8, 6))
sns.heatmap(correlacao, annot=True, cmap='coolwarm', center=0)
plt.title('Mapa de Calor das Correlações')
plt.show()

4. Pré-processamento para Machine Learning

4.1. Codificação de variáveis categóricas

from sklearn.preprocessing import LabelEncoder, OneHotEncoder

# Label Encoding para variável ordinal
le = LabelEncoder()
df['categoria_encoded'] = le.fit_transform(df['categoria'])

# One-Hot Encoding para variáveis nominais
df_encoded = pd.get_dummies(df, columns=['regiao'], prefix='regiao')

4.2. Normalização e padronização

from sklearn.preprocessing import MinMaxScaler, StandardScaler

# Normalização (0-1)
scaler_minmax = MinMaxScaler()
df[['preco_norm', 'quantidade_norm']] = scaler_minmax.fit_transform(df[['preco', 'quantidade']])

# Padronização (média 0, desvio 1)
scaler_std = StandardScaler()
df[['preco_std', 'quantidade_std']] = scaler_std.fit_transform(df[['preco', 'quantidade']])

4.3. Divisão dos dados

from sklearn.model_selection import train_test_split

# Separando features e target
X = df[['preco', 'quantidade', 'categoria_encoded']]
y = df['valor']

# Divisão treino-teste
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Divisão com validação
X_train, X_temp, y_train, y_temp = train_test_split(X_train, y_train, test_size=0.25, random_state=42)
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)

5. Modelagem Preditiva com Scikit-learn

5.1. Regressão linear e logística

from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.metrics import r2_score, accuracy_score, confusion_matrix

# Regressão Linear
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred_lr = lr.predict(X_test)
print(f'R² Score: {r2_score(y_test, y_pred_lr):.3f}')

# Regressão Logística (classificação)
logreg = LogisticRegression()
logreg.fit(X_train, (y_train > y_train.median()).astype(int))
y_pred_log = logreg.predict(X_test)
print(f'Acurácia: {accuracy_score((y_test > y_test.median()).astype(int), y_pred_log):.3f}')
print(f'Matriz de Confusão:\n{confusion_matrix((y_test > y_test.median()).astype(int), y_pred_log)}')

5.2. Árvores de decisão e Random Forest

from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor

# Árvore de Decisão
dt = DecisionTreeRegressor(max_depth=5, random_state=42)
dt.fit(X_train, y_train)
print(f'Importância das Features: {dict(zip(X.columns, dt.feature_importances_))}')

# Random Forest
rf = RandomForestRegressor(n_estimators=100, max_depth=10, random_state=42)
rf.fit(X_train, y_train)
y_pred_rf = rf.predict(X_test)
print(f'R² Random Forest: {r2_score(y_test, y_pred_rf):.3f}')

5.3. Validação cruzada e tuning

from sklearn.model_selection import cross_val_score, GridSearchCV

# Validação cruzada
scores = cross_val_score(rf, X_train, y_train, cv=5, scoring='r2')
print(f'Cross-Validation R²: {scores.mean():.3f} (+/- {scores.std() * 2:.3f})')

# Grid Search para tuning
param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [5, 10, None],
    'min_samples_split': [2, 5, 10]
}

grid_search = GridSearchCV(RandomForestRegressor(random_state=42), param_grid, cv=3, scoring='r2')
grid_search.fit(X_train, y_train)
print(f'Melhores Parâmetros: {grid_search.best_params_}')
print(f'Melhor R² CV: {grid_search.best_score_:.3f}')

6. Tópicos Avançados e Boas Práticas

6.1. Pipelines para automatizar processos

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer

# Criando pipeline completo
preprocessor = ColumnTransformer(
    transformers=[
        ('num', Pipeline([
            ('imputer', SimpleImputer(strategy='median')),
            ('scaler', StandardScaler())
        ]), ['preco', 'quantidade']),
        ('cat', OneHotEncoder(), ['categoria'])
    ])

pipeline = Pipeline([
    ('preprocessor', preprocessor),
    ('regressor', RandomForestRegressor(n_estimators=100, random_state=42))
])

pipeline.fit(X_train, y_train)
print(f'Pipeline R²: {r2_score(y_test, pipeline.predict(X_test)):.3f}')

6.2. Salvando e carregando modelos

import joblib

# Salvando modelo
joblib.dump(pipeline, 'modelo_vendas.pkl')

# Carregando modelo posteriormente
modelo_carregado = joblib.load('modelo_vendas.pkl')
novas_previsoes = modelo_carregado.predict(novos_dados)

6.3. Dicas de performance

import numpy as np

# Vetorização com NumPy (evite loops)
# Ruim:
soma_lenta = 0
for i in range(len(arr)):
    soma_lenta += arr[i] ** 2

# Bom (vetorizado):
soma_rapida = np.sum(arr ** 2)

# Paralelismo básico com Scikit-learn
rf_paralelo = RandomForestRegressor(n_estimators=100, n_jobs=-1, random_state=42)

7. Considerações Finais e Próximos Passos

7.1. Resumo do fluxo completo

O fluxo completo de dados brutos a modelo em produção segue estas etapas:
1. Coleta e importação de dados de diversas fontes
2. Limpeza e pré-processamento para tratar inconsistências
3. Análise exploratória para entender padrões e relações
4. Feature engineering para criar variáveis preditivas
5. Modelagem com validação e otimização de hiperparâmetros
6. Avaliação com métricas apropriadas ao problema
7. Implantação do pipeline em produção

7.2. Referências para aprofundamento

Para continuar evoluindo, explore ferramentas como Apache Spark para big data, Dask para computação paralela em datasets maiores que a memória, e MLflow para gerenciamento do ciclo de vida de modelos. A prática constante com datasets reais e a participação em competições como as do Kaggle são excelentes formas de consolidar o aprendizado.

7.3. Integração com outras ferramentas

O ecossistema Python permite integração com:
- Apache Spark: Processamento distribuído via PySpark
- Dask: Paralelismo para datasets que não cabem em memória
- MLflow: Rastreamento de experimentos e versionamento de modelos
- FastAPI: Criação de APIs para servir modelos em produção

Referências