Python

Introdução ao Data Science com Python Já leu

10 min de leitura

Introdução ao Data Science com Python
Data Science é a disciplina que extrai conhecimento e insights de dados — combinando estatística, programação e domínio do problema. Python se tornou a linguagem dominante nessa área por um motivo simples: seu ecossistem

Data Science é a disciplina que extrai conhecimento e insights de dados — combinando estatística, programação e domínio do problema. Python se tornou a linguagem dominante nessa área por um motivo simples: seu ecossistema de bibliotecas é incomparável. NumPy, pandas, Matplotlib e Seaborn formam a base sobre a qual toda análise de dados em Python é construída. Neste artigo apresentamos esse ecossistema de forma sistemática e prática.


O Ecossistema de Data Science

Dados brutos
     │
     ▼
┌─────────────┐   coleta e limpeza    ┌──────────────┐
│   pandas    │ ◄──────────────────── │  requests /  │
│  (tabelas)  │                       │  scrapy / sql│
└──────┬──────┘                       └──────────────┘
       │ arrays numéricos
       ▼
┌─────────────┐   visualização        ┌──────────────┐
│    NumPy    │ ────────────────────► │  Matplotlib  │
│  (vetores)  │                       │   Seaborn    │
└──────┬──────┘                       └──────────────┘
       │ modelagem
       ▼
┌─────────────┐   avaliação           ┌──────────────┐
│ scikit-learn│ ────────────────────► │   métricas / │
│    (ML)     │                       │   relatórios │
└─────────────┘                       └──────────────┘
pip install numpy pandas matplotlib seaborn scipy jupyter

NumPy: Computação Numérica

NumPy é a fundação de todo o ecossistema científico Python — arrays multidimensionais com operações vetorizadas, muito mais rápidas que listas Python puras.

import numpy as np

# Criando arrays
a = np.array([1, 2, 3, 4, 5])
b = np.array([10, 20, 30, 40, 50])

print(a.dtype)    # int64
print(a.shape)    # (5,)
print(a.ndim)     # 1

# Operações vetorizadas — sem loop explícito
print(a + b)      # [11 22 33 44 55]
print(a * 2)      # [ 2  4  6  8 10]
print(a ** 2)     # [ 1  4  9 16 25]
print(np.sqrt(a)) # [1.   1.41 1.73 2.   2.24]

# Comparações vetorizadas
print(a > 3)      # [False False False  True  True]
print(a[a > 3])   # [4 5] — indexação booleana

Arrays Multidimensionais

# Matriz 3x4
matriz = np.array([
    [1,  2,  3,  4],
    [5,  6,  7,  8],
    [9, 10, 11, 12]
])

print(matriz.shape)      # (3, 4)
print(matriz[1, 2])      # 7 — linha 1, coluna 2
print(matriz[:, 0])      # [1 5 9] — toda a coluna 0
print(matriz[0, :])      # [1 2 3 4] — toda a linha 0
print(matriz[1:, 2:])    # submatriz

# Criando arrays especiais
zeros = np.zeros((3, 4))
uns   = np.ones((2, 5))
ident = np.eye(3)            # matriz identidade
seq   = np.arange(0, 20, 2)  # [0 2 4 ... 18]
lin   = np.linspace(0, 1, 5) # [0.   0.25  0.5   0.75  1.]
rand  = np.random.rand(3, 3) # valores aleatórios 0-1

Álgebra Linear e Estatística

a = np.array([2, 4, 4, 4, 5, 5, 7, 9])

print(f"Média:     {np.mean(a):.2f}")      # 5.0
print(f"Mediana:   {np.median(a):.2f}")    # 4.5
print(f"Desvio:    {np.std(a):.2f}")       # 2.0
print(f"Variância: {np.var(a):.2f}")       # 4.0
print(f"Mínimo:    {np.min(a)}")           # 2
print(f"Máximo:    {np.max(a)}")           # 9
print(f"Soma:      {np.sum(a)}")           # 40
print(f"Percentil 75: {np.percentile(a, 75)}")  # 5.25

# Produto matricial
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B)       # produto matricial
print(np.dot(A, B))

# Autovalores e autovetores
vals, vecs = np.linalg.eig(A)
print(vals)

# Resolução de sistema linear Ax = b
A = np.array([[2, 1], [1, 3]], dtype=float)
b = np.array([5, 10], dtype=float)
x = np.linalg.solve(A, b)
print(x)   # solução do sistema

pandas: Análise de Dados Tabulares

pandas é o Excel do Python — mas infinitamente mais poderoso.

import pandas as pd

# Criando DataFrame
df = pd.DataFrame({
    "nome":       ["Ana", "Bruno", "Carla", "Diego", "Elena"],
    "idade":      [23, 35, 28, 42, 31],
    "cidade":     ["Recife", "SP", "RJ", "SP", "Recife"],
    "salario":    [4500.0, 8200.0, 6300.0, 12000.0, 5800.0],
    "ativo":      [True, True, False, True, True]
})

# Informações básicas
print(df.shape)          # (5, 5)
print(df.dtypes)         # tipos de cada coluna
print(df.describe())     # estatísticas descritivas
print(df.info())         # visão geral + memória usada
print(df.head(3))        # primeiras 3 linhas
print(df.tail(2))        # últimas 2 linhas

Seleção e Filtragem

# Selecionando colunas
print(df["nome"])                    # Series
print(df[["nome", "salario"]])       # DataFrame

# loc — por rótulo
print(df.loc[0])                     # linha 0
print(df.loc[1:3, ["nome", "idade"]]) # linhas 1-3, colunas específicas

# iloc — por posição inteira
print(df.iloc[0, 1])                 # linha 0, coluna 1
print(df.iloc[:3, :2])              # primeiras 3 linhas, 2 colunas

# Filtrando
ativos    = df[df["ativo"] == True]
sp        = df[df["cidade"] == "SP"]
alto_sal  = df[df["salario"] > 6000]
sp_ativo  = df[(df["cidade"] == "SP") & (df["ativo"] == True)]
recife_ou_rj = df[df["cidade"].isin(["Recife", "RJ"])]

# query() — sintaxe SQL-like
resultado = df.query("salario > 5000 and ativo == True")

Transformações e Cálculos

# Novas colunas
df["bonus"]        = df["salario"] * 0.1
df["faixa_etaria"] = pd.cut(
    df["idade"],
    bins=[0, 25, 35, 50, 100],
    labels=["Jovem", "Adulto", "Meia-idade", "Sênior"]
)

# Aplicando funções
df["nome_upper"] = df["nome"].str.upper()
df["salario_k"]  = df["salario"].apply(lambda x: f"R$ {x/1000:.1f}k")

# Operações sobre grupos
por_cidade = df.groupby("cidade").agg(
    total_funcionarios=("nome",    "count"),
    salario_medio=     ("salario", "mean"),
    salario_total=     ("salario", "sum"),
    idade_media=       ("idade",   "mean")
).round(2)

print(por_cidade)

# Pivot table
pivot = df.pivot_table(
    values="salario",
    index="cidade",
    columns="ativo",
    aggfunc="mean"
)
print(pivot)

Limpeza de Dados

import numpy as np

# Dataset com problemas
df_sujo = pd.DataFrame({
    "nome":    ["Ana", "Bruno", None,  "Diego", "Ana",    "Elena"],
    "idade":   [23,    35,      28,    None,    23,       -5],
    "salario": [4500,  8200,    6300,  12000,   4500,     np.nan],
    "email":   ["ana@email.com", "bruno@email.com", "invalido",
                "diego@email.com", "ana@email.com", "elena@email.com"]
})

print("=== Dados sujos ===")
print(df_sujo)
print(f"\nValores nulos:\n{df_sujo.isnull().sum()}")
print(f"\nDuplicatas: {df_sujo.duplicated().sum()}")

# 1. Removendo duplicatas
df_limpo = df_sujo.drop_duplicates()

# 2. Tratando valores nulos
df_limpo["nome"].fillna("Desconhecido", inplace=True)
df_limpo["salario"].fillna(df_limpo["salario"].median(), inplace=True)
df_limpo.dropna(subset=["idade"], inplace=True)  # remove linhas sem idade

# 3. Corrigindo valores inválidos
df_limpo = df_limpo[df_limpo["idade"] > 0]

# 4. Validando e-mails
df_limpo["email_valido"] = df_limpo["email"].str.contains(
    r"^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$",
    regex=True
)

# 5. Normalizando tipos
df_limpo["idade"]   = df_limpo["idade"].astype(int)
df_limpo["salario"] = df_limpo["salario"].astype(float)

print("\n=== Dados limpos ===")
print(df_limpo)

Matplotlib: Visualização Fundamental

import matplotlib.pyplot as plt
import numpy as np

# Configuração global
plt.rcParams.update({
    "figure.figsize":  (10, 6),
    "axes.spines.top":    False,
    "axes.spines.right":  False,
    "font.family":     "DejaVu Sans"
})


def graficos_basicos():
    fig, axes = plt.subplots(2, 3, figsize=(15, 10))
    fig.suptitle("Tipos de Gráficos", fontsize=16, fontweight="bold")

    # 1. Linha
    x  = np.linspace(0, 10, 100)
    ax = axes[0, 0]
    ax.plot(x, np.sin(x), label="sen(x)", color="#2E75B6")
    ax.plot(x, np.cos(x), label="cos(x)", color="#C00000", linestyle="--")
    ax.set_title("Gráfico de Linha")
    ax.legend()
    ax.grid(alpha=0.3)

    # 2. Barras
    categorias = ["Jan", "Fev", "Mar", "Abr", "Mai"]
    valores    = [42, 58, 71, 65, 83]
    ax = axes[0, 1]
    bars = ax.bar(categorias, valores, color="#2E75B6", alpha=0.8)
    ax.bar_label(bars, padding=2)
    ax.set_title("Gráfico de Barras")

    # 3. Dispersão
    np.random.seed(42)
    x = np.random.randn(100)
    y = 2 * x + np.random.randn(100)
    ax = axes[0, 2]
    ax.scatter(x, y, alpha=0.6, color="#2E75B6")
    ax.set_title("Dispersão")

    # 4. Histograma
    dados = np.random.normal(170, 10, 500)
    ax = axes[1, 0]
    ax.hist(dados, bins=30, color="#2E75B6", alpha=0.8, edgecolor="white")
    ax.set_title("Histograma")
    ax.set_xlabel("Altura (cm)")

    # 5. Pizza
    labels = ["Aprovados", "Reprovados", "Recuperação"]
    sizes  = [65, 20, 15]
    cores  = ["#375623", "#C00000", "#F5A623"]
    ax = axes[1, 1]
    ax.pie(sizes, labels=labels, colors=cores, autopct="%1.1f%%", startangle=90)
    ax.set_title("Pizza")

    # 6. Box Plot
    dados_box = [np.random.normal(loc, 1, 100) for loc in [2, 3, 5, 8]]
    ax = axes[1, 2]
    ax.boxplot(dados_box, labels=["A", "B", "C", "D"], patch_artist=True)
    ax.set_title("Box Plot")

    plt.tight_layout()
    plt.savefig("graficos_basicos.png", dpi=150, bbox_inches="tight")
    plt.show()


graficos_basicos()

Seaborn: Visualizações Estatísticas

import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt

# Dataset de exemplo
np.random.seed(42)
df_vis = pd.DataFrame({
    "nota":       np.random.normal(7.0, 1.5, 200).clip(0, 10),
    "horas_estudo": np.random.uniform(1, 8, 200),
    "turma":      np.random.choice(["A", "B", "C"], 200),
    "aprovado":   lambda x: None
})
df_vis["aprovado"] = (df_vis["nota"] >= 6).map({True: "Sim", False: "Não"})

sns.set_theme(style="whitegrid", palette="muted")
fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# 1. Distribuição de notas
sns.histplot(
    data=df_vis, x="nota", hue="aprovado",
    multiple="stack", bins=20, ax=axes[0, 0]
)
axes[0, 0].set_title("Distribuição de Notas")
axes[0, 0].axvline(6, color="red", linestyle="--", label="Mínimo")

# 2. Boxplot por turma
sns.boxplot(
    data=df_vis, x="turma", y="nota",
    palette="Blues", ax=axes[0, 1]
)
axes[0, 1].set_title("Notas por Turma")

# 3. Scatter com regressão
sns.regplot(
    data=df_vis,
    x="horas_estudo", y="nota",
    scatter_kws={"alpha": 0.4},
    line_kws={"color": "red"},
    ax=axes[1, 0]
)
axes[1, 0].set_title("Horas de Estudo vs Nota")

# 4. Heatmap de correlação
correlacao = df_vis[["nota", "horas_estudo"]].corr()
sns.heatmap(
    correlacao,
    annot=True, fmt=".2f",
    cmap="Blues", center=0,
    ax=axes[1, 1]
)
axes[1, 1].set_title("Correlação")

plt.suptitle("Análise de Desempenho Escolar", fontsize=16, fontweight="bold")
plt.tight_layout()
plt.savefig("analise_escolar.png", dpi=150, bbox_inches="tight")
plt.show()

Análise Exploratória Completa

def analise_exploratoria(df: pd.DataFrame, coluna_alvo: str):
    """EDA — Exploratory Data Analysis padronizada."""

    print("=" * 50)
    print("ANÁLISE EXPLORATÓRIA DE DADOS")
    print("=" * 50)

    # 1. Visão geral
    print(f"\n📊 Dimensões: {df.shape[0]} linhas × {df.shape[1]} colunas")
    print(f"\n📋 Tipos de dados:\n{df.dtypes}")
    print(f"\n🔍 Valores nulos:\n{df.isnull().sum()}")
    print(f"\n🔁 Duplicatas: {df.duplicated().sum()}")

    # 2. Estatísticas da variável alvo
    alvo = df[coluna_alvo]
    print(f"\n📈 Estatísticas de '{coluna_alvo}':")
    print(f"  Média:      {alvo.mean():.2f}")
    print(f"  Mediana:    {alvo.median():.2f}")
    print(f"  Desvio:     {alvo.std():.2f}")
    print(f"  Assimetria: {alvo.skew():.2f}")
    print(f"  Curtose:    {alvo.kurtosis():.2f}")

    # 3. Correlações com a variável alvo
    numericas  = df.select_dtypes(include=[np.number])
    correlacoes = numericas.corr()[coluna_alvo].sort_values(ascending=False)
    print(f"\n🔗 Correlações com '{coluna_alvo}':\n{correlacoes}")

    # 4. Distribuição de categorias
    categoricas = df.select_dtypes(include=["object", "category"])
    for col in categoricas.columns:
        print(f"\n📌 {col}:")
        print(df[col].value_counts().head(5))


analise_exploratoria(df_vis, "nota")

SciPy: Estatística Avançada

from scipy import stats

# Teste t — comparar médias de dois grupos
turma_a = df_vis[df_vis["turma"] == "A"]["nota"]
turma_b = df_vis[df_vis["turma"] == "B"]["nota"]

t_stat, p_valor = stats.ttest_ind(turma_a, turma_b)
print(f"Teste t: t={t_stat:.3f}, p={p_valor:.3f}")
print(f"Diferença significativa: {'Sim' if p_valor < 0.05 else 'Não'}")

# Teste de normalidade
stat, p = stats.shapiro(turma_a)
print(f"\nShapiro-Wilk: stat={stat:.3f}, p={p:.3f}")
print(f"Distribuição normal: {'Sim' if p > 0.05 else 'Não'}")

# Intervalo de confiança
media    = turma_a.mean()
ic       = stats.t.interval(
    confidence=0.95,
    df=len(turma_a) - 1,
    loc=media,
    scale=stats.sem(turma_a)
)
print(f"\nIC 95%: [{ic[0]:.2f}, {ic[1]:.2f}]")

# Regressão linear
slope, intercept, r, p, se = stats.linregress(
    df_vis["horas_estudo"], df_vis["nota"]
)
print(f"\nRegressão Linear:")
print(f"  Inclinação:  {slope:.3f}")
print(f"  Intercepto: {intercept:.3f}")
print(f"  R²:          {r**2:.3f}")

Resumo

  • NumPy fornece arrays multidimensionais com operações vetorizadas — base de todo o ecossistema científico
  • pandas organiza dados em DataFrames com operações de seleção, transformação, agrupamento e limpeza
  • groupby().agg() resume dados por categoria de forma expressiva e eficiente
  • Limpeza de dados inclui tratar nulos, remover duplicatas e corrigir tipos e valores inválidos
  • Matplotlib oferece controle total sobre gráficos; Seaborn adiciona visualizações estatísticas elegantes
  • EDA — Exploratory Data Analysis — é sempre o primeiro passo antes de qualquer modelagem
  • SciPy complementa NumPy com testes estatísticos, distribuições e regressões

Referências e Leituras Complementares

  • NumPy — documentação oficial — https://numpy.org/doc/stable/
  • pandas — documentação oficial — https://pandas.pydata.org/docs/
  • Matplotlib — documentação oficial — https://matplotlib.org/stable/
  • Seaborn — documentação oficial — https://seaborn.pydata.org/
  • SciPy — documentação oficial — https://docs.scipy.org/doc/scipy/
  • MCKINNEY, Wes. Python for Data Analysis. 3. ed. O'Reilly Media, 2022. — o livro definitivo sobre pandas, escrito pelo seu criador.
  • VANDERPLAS, Jake. Python Data Science Handbook. O'Reilly Media, 2016. — guia completo do ecossistema científico Python, disponível gratuitamente em https://jakevdp.github.io/PythonDataScienceHandbook/
  • GÉRON, Aurélien. Hands-On Machine Learning. 3. ed. O'Reilly Media, 2022. Cap. 2 — pipeline completo de Data Science do início ao fim.
Comentários

Mais em Python

Artigo 38 — Processamento de Linguagem Natural (NLP)
Artigo 38 — Processamento de Linguagem Natural (NLP)

Processamento de Linguagem Natural é o campo da IA que lida com texto e fala...

Web Scraping com BeautifulSoup e Selenium
Web Scraping com BeautifulSoup e Selenium

Nem toda informação que você precisa está disponível em uma API. Preços de pr...

Decoradores e Metaprogramação
Decoradores e Metaprogramação

Decoradores s&atilde;o um dos recursos mais elegantes do Python. Eles permite...