Python

Artigo 40 — Análise de Dados com Pandas Avançado e Plotly Já leu

19 min de leitura

Artigo 40 — Análise de Dados com Pandas Avançado e Plotly
No Artigo 35 vimos os fundamentos do pandas. Neste artigo aprofundamos as técnicas mais poderosas da biblioteca — operações de janela, merge, reshape e

Artigo 40 — Análise de Dados com Pandas Avançado e Plotly

Prof. Ricardo Matos Módulo 7 · Data Science e Machine Learning · Artigo 40 de 52


Introdução

No Artigo 35 vimos os fundamentos do pandas. Neste artigo aprofundamos as técnicas mais poderosas da biblioteca — operações de janela, merge, reshape e otimização de memória — e introduzimos o Plotly, a biblioteca de visualização interativa que transforma análises em dashboards prontos para a web. A combinação pandas avançado + Plotly é o padrão em ciência de dados aplicada ao negócio.


Instalação

pip install plotly pandas numpy dash

Pandas Avançado: Operações de Merge e Join

import pandas as pd
import numpy as np

# DataFrames de exemplo
alunos = pd.DataFrame({
    "id":      [1, 2, 3, 4, 5],
    "nome":    ["Ana", "Bruno", "Carla", "Diego", "Elena"],
    "turma_id":[1, 1, 2, 2, 3],
    "ativo":   [True, True, True, False, True]
})

turmas = pd.DataFrame({
    "id":       [1, 2, 3, 4],
    "nome":     ["Turma A", "Turma B", "Turma C", "Turma D"],
    "turno":    ["Manhã", "Tarde", "Noite", "Manhã"],
    "capacidade":[30, 25, 20, 30]
})

notas = pd.DataFrame({
    "aluno_id":    [1, 1, 2, 3, 3, 4, 5],
    "disciplina":  ["Mat", "Port", "Mat", "Mat", "Port", "Mat", "Port"],
    "nota":        [9.5, 8.0, 7.0, 8.5, 6.0, 5.5, 9.0]
})


# INNER JOIN — apenas correspondências
inner = pd.merge(alunos, turmas, left_on="turma_id", right_on="id",
                 suffixes=("_aluno", "_turma"))
print("=== INNER JOIN ===")
print(inner[["nome_aluno", "nome_turma", "turno"]])


# LEFT JOIN — todos os alunos, mesmo sem turma
left = pd.merge(alunos, turmas, left_on="turma_id", right_on="id", how="left")

# OUTER JOIN — tudo de ambos
outer = pd.merge(alunos, turmas, left_on="turma_id", right_on="id", how="outer")


# Join múltiplo — alunos + turmas + notas
completo = (
    alunos
    .merge(turmas, left_on="turma_id", right_on="id", suffixes=("", "_turma"))
    .merge(notas,  left_on="id",       right_on="aluno_id")
    [["nome", "nome_turma", "turno", "disciplina", "nota"]]
)
print("\n=== Dataset Completo ===")
print(completo)


# Concatenação
semestre1 = pd.DataFrame({
    "aluno": ["Ana", "Bruno"],
    "nota":  [8.5, 7.0],
    "semestre": ["S1", "S1"]
})
semestre2 = pd.DataFrame({
    "aluno": ["Ana", "Bruno", "Carla"],
    "nota":  [9.0, 7.5, 8.0],
    "semestre": ["S2", "S2", "S2"]
})

historico = pd.concat([semestre1, semestre2], ignore_index=True)
print("\n=== Histórico Concatenado ===")
print(historico)

Reshape: Pivot e Melt

# PIVOT — de linhas para colunas
notas_pivot = notas.pivot(
    index="aluno_id",
    columns="disciplina",
    values="nota"
).reset_index()
notas_pivot.columns.name = None
print("=== Pivot ===")
print(notas_pivot)


# PIVOT TABLE — com agregação
pivot_agg = pd.pivot_table(
    completo,
    values="nota",
    index="nome",
    columns="disciplina",
    aggfunc="mean",
    fill_value=0,
    margins=True,      # totais
    margins_name="Média"
)
print("\n=== Pivot Table com Totais ===")
print(pivot_agg.round(2))


# MELT — de colunas para linhas (inverso do pivot)
df_wide = pd.DataFrame({
    "aluno": ["Ana", "Bruno"],
    "Mat":   [9.5, 7.0],
    "Port":  [8.0, 6.5],
    "Hist":  [7.5, 8.0],
})

df_long = pd.melt(
    df_wide,
    id_vars=["aluno"],
    value_vars=["Mat", "Port", "Hist"],
    var_name="disciplina",
    value_name="nota"
)
print("\n=== Melt (wide → long) ===")
print(df_long)


# STACK e UNSTACK
df_stacked = notas_pivot.set_index("aluno_id").stack()
print("\n=== Stack ===")
print(df_stacked.head(8))

Operações de Janela (Window Functions)

# Dataset temporal de notas ao longo do ano
np.random.seed(42)
datas = pd.date_range("2024-01-01", periods=52, freq="W")

df_temp = pd.DataFrame({
    "data":    datas,
    "aluno":   np.random.choice(["Ana", "Bruno", "Carla"], 52),
    "nota":    np.random.uniform(5, 10, 52).round(1),
    "horas":   np.random.randint(2, 10, 52),
})
df_temp = df_temp.sort_values(["aluno", "data"]).reset_index(drop=True)


# Rolling — média móvel
df_temp["media_movel_4s"] = (
    df_temp.groupby("aluno")["nota"]
    .transform(lambda x: x.rolling(window=4, min_periods=1).mean())
    .round(2)
)

# Expanding — média acumulada
df_temp["media_acumulada"] = (
    df_temp.groupby("aluno")["nota"]
    .transform(lambda x: x.expanding().mean())
    .round(2)
)

# Shift — nota da semana anterior
df_temp["nota_anterior"] = (
    df_temp.groupby("aluno")["nota"]
    .shift(1)
)

# Variação em relação à semana anterior
df_temp["variacao"] = (
    df_temp["nota"] - df_temp["nota_anterior"]
).round(2)

# Rank dentro de cada grupo
df_temp["rank_semana"] = (
    df_temp.groupby("data")["nota"]
    .rank(method="dense", ascending=False)
    .astype(int)
)

print("=== Window Functions ===")
print(df_temp[df_temp["aluno"] == "Ana"].head(8).to_string())

GroupBy Avançado

# Múltiplas agregações simultâneas
stats = df_temp.groupby("aluno").agg(
    media=        ("nota",  "mean"),
    mediana=      ("nota",  "median"),
    desvio=       ("nota",  "std"),
    melhor=       ("nota",  "max"),
    pior=         ("nota",  "min"),
    total_horas=  ("horas", "sum"),
    semanas=      ("nota",  "count"),
).round(2)
print("=== Estatísticas por Aluno ===")
print(stats)


# Apply com função customizada
def resumo_aluno(grupo):
    notas_acima_7 = (grupo["nota"] >= 7).sum()
    tendencia     = np.polyfit(range(len(grupo)), grupo["nota"], 1)[0]
    return pd.Series({
        "notas_acima_7":  notas_acima_7,
        "tendencia":      round(tendencia, 4),
        "melhorando":     tendencia > 0
    })

resumos = df_temp.groupby("aluno").apply(resumo_aluno)
print("\n=== Análise de Tendência ===")
print(resumos)


# Transform — preserva o índice original
df_temp["media_turma"] = df_temp.groupby("aluno")["nota"].transform("mean")
df_temp["acima_media"]  = df_temp["nota"] > df_temp["media_turma"]


# Filter — filtra grupos inteiros
alunos_bons = df_temp.groupby("aluno").filter(
    lambda g: g["nota"].mean() >= 7.5
)
print(f"\nAlunos com média ≥ 7.5: {alunos_bons['aluno'].unique()}")

Otimização de Memória

def otimizar_dataframe(df: pd.DataFrame) -> pd.DataFrame:
    """Reduz uso de memória ajustando tipos de dados."""
    df_opt = df.copy()
    mem_antes = df_opt.memory_usage(deep=True).sum() / 1024 ** 2

    for col in df_opt.columns:
        tipo = df_opt[col].dtype

        # Inteiros
        if tipo in ["int64", "int32"]:
            c_min = df_opt[col].min()
            c_max = df_opt[col].max()
            if c_min >= np.iinfo(np.int8).min and c_max <= np.iinfo(np.int8).max:
                df_opt[col] = df_opt[col].astype(np.int8)
            elif c_min >= np.iinfo(np.int16).min and c_max <= np.iinfo(np.int16).max:
                df_opt[col] = df_opt[col].astype(np.int16)
            elif c_min >= np.iinfo(np.int32).min and c_max <= np.iinfo(np.int32).max:
                df_opt[col] = df_opt[col].astype(np.int32)

        # Floats
        elif tipo == "float64":
            df_opt[col] = df_opt[col].astype(np.float32)

        # Strings com baixa cardinalidade → category
        elif tipo == "object":
            num_unicos = df_opt[col].nunique()
            if num_unicos / len(df_opt) < 0.5:
                df_opt[col] = df_opt[col].astype("category")

    mem_depois = df_opt.memory_usage(deep=True).sum() / 1024 ** 2
    reducao    = (1 - mem_depois / mem_antes) * 100

    print(f"Memória antes:  {mem_antes:.2f} MB")
    print(f"Memória depois: {mem_depois:.2f} MB")
    print(f"Redução:        {reducao:.1f}%")

    return df_opt


# Testando com dataset grande
df_grande = pd.DataFrame({
    "id":       range(100_000),
    "nota":     np.random.uniform(0, 10, 100_000),
    "faltas":   np.random.randint(0, 30, 100_000),
    "turma":    np.random.choice(["A", "B", "C", "D"], 100_000),
    "aprovado": np.random.choice([True, False], 100_000),
})

df_otimizado = otimizar_dataframe(df_grande)

Plotly: Visualizações Interativas

import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np


# Dataset para visualizações
np.random.seed(42)
df_vis = pd.DataFrame({
    "aluno":     np.random.choice(["Ana", "Bruno", "Carla", "Diego"], 200),
    "nota":      np.random.normal(7.0, 1.5, 200).clip(0, 10),
    "horas":     np.random.uniform(1, 10, 200),
    "faltas":    np.random.randint(0, 15, 200),
    "turma":     np.random.choice(["A", "B", "C"], 200),
    "semestre":  np.random.choice(["S1", "S2"], 200),
})
df_vis["aprovado"] = (df_vis["nota"] >= 6).map({True: "Aprovado", False: "Reprovado"})

Gráficos Básicos com Plotly Express

# Histograma interativo
fig = px.histogram(
    df_vis,
    x="nota",
    color="aprovado",
    nbins=30,
    title="Distribuição de Notas",
    labels={"nota": "Nota", "count": "Frequência"},
    color_discrete_map={"Aprovado": "#375623", "Reprovado": "#C00000"},
    barmode="overlay",
    opacity=0.7,
    template="plotly_white"
)
fig.add_vline(x=6, line_dash="dash", line_color="orange",
              annotation_text="Mínimo para aprovação")
fig.write_html("histograma.html")
fig.show()


# Scatter com correlação
fig = px.scatter(
    df_vis,
    x="horas", y="nota",
    color="aprovado",
    size="faltas",
    hover_data=["aluno", "turma"],
    trendline="ols",
    title="Horas de Estudo vs Nota",
    labels={"horas": "Horas de Estudo", "nota": "Nota Final"},
    color_discrete_map={"Aprovado": "#2E75B6", "Reprovado": "#C00000"},
    template="plotly_white"
)
fig.write_html("scatter.html")
fig.show()


# Box plot por turma
fig = px.box(
    df_vis,
    x="turma", y="nota",
    color="semestre",
    points="outliers",
    title="Distribuição de Notas por Turma e Semestre",
    template="plotly_white"
)
fig.write_html("boxplot.html")
fig.show()

Plotly Graph Objects: Controle Total

# Dashboard com subplots
fig = make_subplots(
    rows=2, cols=2,
    subplot_titles=(
        "Distribuição de Notas",
        "Horas de Estudo vs Nota",
        "Aprovação por Turma",
        "Evolução Semanal"
    ),
    vertical_spacing=0.15
)

# Plot 1: Histograma
for status, cor in [("Aprovado", "#375623"), ("Reprovado", "#C00000")]:
    subset = df_vis[df_vis["aprovado"] == status]["nota"]
    fig.add_trace(
        go.Histogram(x=subset, name=status, marker_color=cor,
                     opacity=0.7, nbinsx=20),
        row=1, col=1
    )

# Plot 2: Scatter
for turma, cor in [("A", "#2E75B6"), ("B", "#F5A623"), ("C", "#375623")]:
    subset = df_vis[df_vis["turma"] == turma]
    fig.add_trace(
        go.Scatter(
            x=subset["horas"], y=subset["nota"],
            mode="markers", name=f"Turma {turma}",
            marker=dict(color=cor, size=6, opacity=0.6)
        ),
        row=1, col=2
    )

# Plot 3: Barras empilhadas
contagem = df_vis.groupby(["turma", "aprovado"]).size().reset_index(name="count")
for status, cor in [("Aprovado", "#375623"), ("Reprovado", "#C00000")]:
    subset = contagem[contagem["aprovado"] == status]
    fig.add_trace(
        go.Bar(x=subset["turma"], y=subset["count"],
               name=status, marker_color=cor,
               showlegend=False),
        row=2, col=1
    )

# Plot 4: Linha temporal
df_temp_agg = df_temp.groupby(["data", "aluno"])["nota"].mean().reset_index()
for aluno, cor in [("Ana", "#2E75B6"), ("Bruno", "#C00000"), ("Carla", "#375623")]:
    subset = df_temp_agg[df_temp_agg["aluno"] == aluno]
    fig.add_trace(
        go.Scatter(x=subset["data"], y=subset["nota"],
                   mode="lines+markers", name=aluno,
                   line=dict(color=cor),
                   showlegend=False),
        row=2, col=2
    )

# Layout geral
fig.update_layout(
    title_text="Dashboard de Desempenho Escolar",
    title_font_size=18,
    height=700,
    template="plotly_white",
    barmode="stack",
    legend=dict(
        orientation="h",
        yanchor="bottom", y=1.02,
        xanchor="right",  x=1
    )
)

fig.write_html("dashboard.html")
fig.show()

Gráficos Especializados

# Mapa de calor (Heatmap)
correlacoes = df_vis[["nota", "horas", "faltas"]].corr()

fig = go.Figure(data=go.Heatmap(
    z=correlacoes.values,
    x=correlacoes.columns,
    y=correlacoes.index,
    colorscale="RdBu",
    zmid=0,
    text=correlacoes.round(2).values,
    texttemplate="%{text}",
))
fig.update_layout(title="Correlação entre Variáveis", template="plotly_white")
fig.write_html("heatmap.html")


# Sunburst — hierarquia
df_hier = df_vis.groupby(["turma", "aprovado"]).size().reset_index(name="count")
fig = px.sunburst(
    df_hier,
    path=["turma", "aprovado"],
    values="count",
    color="aprovado",
    color_discrete_map={"Aprovado": "#375623", "Reprovado": "#C00000"},
    title="Aprovação por Turma"
)
fig.write_html("sunburst.html")


# Treemap
fig = px.treemap(
    df_hier,
    path=["turma", "aprovado"],
    values="count",
    color="aprovado",
    title="Treemap — Distribuição por Turma"
)
fig.write_html("treemap.html")


# Gráfico de barras animado
df_animado = df_vis.groupby(["semestre", "turma"])["nota"].mean().reset_index()
fig = px.bar(
    df_animado,
    x="turma", y="nota",
    animation_frame="semestre",
    color="turma",
    range_y=[0, 10],
    title="Evolução da Média por Semestre"
)
fig.write_html("animado.html")

Dash: Dashboard Web Interativo

from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
import numpy as np

app = Dash(__name__)

# Layout do dashboard
app.layout = html.Div([
    html.H1("Dashboard Escolar",
            style={"textAlign": "center", "color": "#1F4E79",
                   "fontFamily": "Arial, sans-serif"}),

    html.Div([
        html.Div([
            html.Label("Turma:"),
            dcc.Dropdown(
                id="filtro-turma",
                options=[{"label": f"Turma {t}", "value": t}
                         for t in ["A", "B", "C"]],
                multi=True,
                value=["A", "B", "C"]
            )
        ], style={"width": "30%", "display": "inline-block", "padding": "10px"}),

        html.Div([
            html.Label("Nota mínima:"),
            dcc.Slider(
                id="filtro-nota",
                min=0, max=10, step=0.5,
                value=0,
                marks={i: str(i) for i in range(11)}
            )
        ], style={"width": "60%", "display": "inline-block", "padding": "10px"}),
    ]),

    html.Div([
        dcc.Graph(id="grafico-distribuicao", style={"width": "50%",
                                                     "display": "inline-block"}),
        dcc.Graph(id="grafico-scatter",      style={"width": "50%",
                                                     "display": "inline-block"}),
    ]),

    html.Div(id="resumo-stats",
             style={"padding": "20px", "fontFamily": "Arial, sans-serif",
                    "background": "#f4f4f4", "borderRadius": "8px",
                    "margin": "10px"}),
])


@app.callback(
    [Output("grafico-distribuicao", "figure"),
     Output("grafico-scatter",      "figure"),
     Output("resumo-stats",         "children")],
    [Input("filtro-turma", "value"),
     Input("filtro-nota",  "value")]
)
def atualizar_dashboard(turmas_sel, nota_min):
    filtrado = df_vis[
        (df_vis["turma"].isin(turmas_sel or [])) &
        (df_vis["nota"] >= nota_min)
    ]

    # Gráfico 1: Distribuição
    fig1 = px.histogram(
        filtrado, x="nota", color="aprovado", nbins=20,
        title="Distribuição de Notas",
        color_discrete_map={"Aprovado": "#375623", "Reprovado": "#C00000"},
        template="plotly_white"
    )

    # Gráfico 2: Scatter
    fig2 = px.scatter(
        filtrado, x="horas", y="nota",
        color="turma", size="faltas",
        title="Horas de Estudo vs Nota",
        template="plotly_white"
    )

    # Estatísticas
    if len(filtrado) > 0:
        media      = filtrado["nota"].mean()
        aprovados  = (filtrado["nota"] >= 6).sum()
        pct_aprov  = aprovados / len(filtrado) * 100
        resumo = [
            html.Strong("Estatísticas do Filtro: "),
            html.Span(f"Total: {len(filtrado)} alunos | "),
            html.Span(f"Média: {media:.2f} | "),
            html.Span(f"Aprovados: {aprovados} ({pct_aprov:.1f}%)")
        ]
    else:
        resumo = [html.Span("Nenhum dado para o filtro selecionado.")]

    return fig1, fig2, resumo


if __name__ == "__main__":
    app.run(debug=True, port=8050)

Resumo

  • pd.merge() combina DataFrames como SQL — inner, left, right e outer join
  • pivot_table agrega com múltiplos índices; melt converte wide → long
  • Window functions com rolling(), expanding() e shift() calculam métricas temporais
  • groupby().apply() aplica funções arbitrárias — mais poderoso que agg()
  • Otimizar dtypes reduz uso de memória em até 70% em datasets grandes
  • Plotly Express cria gráficos interativos com uma linha; Graph Objects oferece controle total
  • Subplots com make_subplots constroem dashboards completos em HTML exportável
  • Dash transforma análises Plotly em aplicações web interativas com callbacks reativos

Referências e Leituras Complementares

  • pandas — guia do usuário avançado — https://pandas.pydata.org/docs/user_guide/
  • Plotly Express — documentação — https://plotly.com/python/plotly-express/
  • Plotly Graph Objects — https://plotly.com/python/graph-objects/
  • Dash — documentação oficial — https://dash.plotly.com/
  • pandas — otimização de memória — https://pandas.pydata.org/docs/user_guide/scale.html
  • MCKINNEY, Wes. Python for Data Analysis. 3. ed. O'Reilly Media, 2022. Cap. 8–10 — merge, reshape e séries temporais com pandas avançado.
  • VANDERPLAS, Jake. Python Data Science Handbook. O'Reilly Media, 2016. Cap. 3 — pandas de ponta a ponta com exemplos detalhados.

Prof. Ricardo Matos — Dominando o Python em 1 Ano · Artigo 40 de 52 Próximo: Artigo 41 — Séries Temporais e Previsão com Prophet e statsmodels


you asked

Repita o plano inicial e me diga o que vimos


claude response

Plano Completo da Série — Estado Atual

Módulo Tema Artigos Status
1 Fundamentos da Linguagem 01–06 ✅ Concluído
2 Estruturas de Dados e Algoritmos 07–12 ✅ Concluído
3 Orientação a Objetos 13–18 ✅ Concluído
4 Arquivos, I/O e Banco de Dados 19–24 ✅ Concluído
5 Python para Web 25–30 ✅ Concluído
6 Automação e Scripts 31–34 ✅ Concluído
7 Data Science e Machine Learning 35–42 🔄 Em andamento
8 Testes, Qualidade e Boas Práticas 43–47 ⬜ Pendente
9 Projetos Reais e Carreira 48–52 ⬜ Pendente

O que foi coberto até agora — Artigo a Artigo

Módulo 1 — Fundamentos da Linguagem (01–06) - 01 · História do Python, filosofia, instalação e primeiro programa - 02 · Variáveis e tipos de dados — int, float, str, bool, NoneType - 03 · Operadores e expressões — aritméticos, lógicos, comparação, identidade - 04 · Estruturas de controle — if, elif, else, operador ternário, truthy/falsy - 05 · Laços de repetição — for, while, break, continue, else em laços - 06 · Funções — definição, parâmetros, escopo LEGB, lambda, docstrings

Módulo 2 — Estruturas de Dados e Algoritmos (07–12) - 07 · Listas — criação, fatiamento, métodos, list comprehension, matrizes - 08 · Tuplas e Sets — imutabilidade, operações de conjunto, deduplicação - 09 · Dicionários — CRUD, iteração, dict comprehension, aninhamento, merge - 10 · Strings em profundidade — métodos, f-strings, regex com módulo re - 11 · Algoritmos de ordenação e busca — bubble, merge sort, busca binária, Timsort - 12 · Recursão e estruturas avançadas — pilhas, filas, árvores binárias, heapq

Módulo 3 — Orientação a Objetos (13–18) - 13 · Classes e objetos — init, atributos, métodos, encapsulamento, @property - 14 · Herança e polimorfismo — super(), duck typing, classes abstratas, MRO - 15 · Interfaces, protocolos e composição — Protocol, Mixins, composição vs herança - 16 · Decoradores e metaprogramação — closures, @wraps, retry, singleton, dataclasses - 17 · Tratamento de exceções — try/except/else/finally, exceções customizadas, with - 18 · Módulos, pacotes e organização de projetos — imports, venv, pip, pyproject.toml

Módulo 4 — Arquivos, I/O e Banco de Dados (19–24) - 19 · Leitura e escrita de arquivos — open, pathlib, CSV, JSON, pickle - 20 · Trabalhando com datas e horas — datetime, timedelta, zoneinfo, dateutil - 21 · Banco de dados com SQLite e SQLAlchemy — CRUD, ORM, Repository, Alembic - 22 · MySQL, MariaDB, PostgreSQL e MongoDB — drivers, psycopg2, pymongo, aggregation - 23 · Consumindo APIs REST — requests, httpx, Session, retry, paginação, async - 24 · Concorrência — threading, multiprocessing, asyncio, ThreadPoolExecutor

Módulo 5 — Python para Web (25–30) - 25 · Flask — rotas, request, response, blueprints, middleware, configuração - 26 · FastAPI — Pydantic, CRUD, Depends, middleware, lifespan, BackgroundTasks - 27 · Autenticação e segurança — bcrypt, JWT, OAuth2, rate limiting, headers HTTP - 28 · Templates Jinja2 e Docker — herança de templates, Dockerfile, Docker Compose - 29 · WebSockets e tempo real — FastAPI WS, SSE, chat, notificações, autenticação WS - 30 · Celery — filas de tarefas, workers, beat scheduler, chain/group/chord, Flower

Módulo 6 — Automação e Scripts (31–34) - 31 · Automação de arquivos e SO — pathlib, shutil, subprocess, watchdog, argparse - 32 · Web scraping — BeautifulSoup, Selenium, paginação, Scrapy, monitor de preços - 33 · Planilhas e PDFs — openpyxl, pandas, ReportLab, PyMuPDF, pipeline de relatórios - 34 · E-mails e APIs de comunicação — smtplib, SendGrid, Twilio SMS/WhatsApp, Slack

Módulo 7 — Data Science e ML (35–40 de 42) - 35 · Introdução ao Data Science — NumPy, pandas, Matplotlib, Seaborn, SciPy, EDA - 36 · Machine Learning com scikit-learn — classificação, regressão, pipeline, GridSearchCV - 37 · Redes Neurais com TensorFlow/Keras — Sequential, Funcional, callbacks, transfer learning - 38 · NLP — NLTK, spaCy, TF-IDF, sentimentos, Word2Vec, Transformers, Hugging Face - 39 · Visão Computacional — Pillow, OpenCV, detecção de bordas, faces, OCR, vídeo - 40 · Pandas avançado e Plotly — merge, pivot, window functions, Dash, dashboards


O que ainda falta no Módulo 7

Artigo Tema
41 Séries Temporais e Previsão com Prophet e statsmodels
42 MLOps: versionamento de modelos, MLflow e deploy de ML

Módulos ainda pendentes

Módulo 8 — Testes, Qualidade e Boas Práticas (43–47) - 43 · Testes com pytest — fixtures, parametrize, mocks, cobertura - 44 · Qualidade de código — linting, formatação, type hints, mypy - 45 · CI/CD com GitHub Actions — pipelines, testes automáticos, deploy - 46 · Logging, monitoramento e observabilidade - 47 · Design Patterns em Python

Módulo 9 — Projetos Reais e Carreira (48–52) - 48 · Projeto 1 — API REST completa com FastAPI + PostgreSQL + Docker - 49 · Projeto 2 — Pipeline de Data Science do zero ao deploy - 50 · Projeto 3 — Bot de automação com scraping + notificações - 51 · Projeto 4 — Dashboard analítico com Dash e banco de dados real - 52 · Carreira — portfólio, GitHub, contribuição open source, mercado Python


Estamos no Artigo 40 de 52 — faltam 12 artigos para concluir a série.

Digite "Sim" para continuar com o Artigo 41 — Séries Temporais e Previsão.


you asked

Sim


claude response

Dominando o Python em 1 Ano

Comentários

Mais em Python

Módulos, Pacotes e Organização de Projetos
Módulos, Pacotes e Organização de Projetos

&Agrave; medida que um programa cresce, colocar tudo em um &uacute;nico arqui...

Dominando o Python
Dominando o Python

Se voc&ecirc; j&aacute; pesquisou sobre programa&ccedil;&atilde;o nos &uacute...

Strings em Profundidade: métodos, formatação e expressões regulares
Strings em Profundidade: métodos, formatação e expressões regulares

No artigo 02 vimos que strings s&atilde;o sequ&ecirc;ncias imut&aacute;veis d...