Pandas: Funções de Janela

Última atualização: 2026-08-26

A Lição 17 introduziu rolling/expanding/ewm. Esta ação aprofunda: agregação de janela personalizada, janelas de tempo avançadas, relacionamentos de parâmetros ewm, e combinações groupby+rolling. As funções de janela são uma ferramenta central para análise quantitativa e processamento de dados de sensores — domine-as, e você domina a capacidade de "ver tendentes através de uma lente deslizante."

⚠️ Nota: O código abaixo deve ser executado em um ambiente local do Python.

1. What You Will Learn


2. Análise da Janela de Frequência Cardíaca do Exercício de Carol

(1) O Problema: A Média de uma Janela de 30 Segundos Não é Suficiente

Os dados da frequência cardíaca durante o exercício de Carol precisam de estatísticas de janela mais ricas — não apenas a média, mas também o máximo e a variabilidade da frequência cardíaca (desvio padrão):

PYTHON
import pandas as pd
import numpy as np

np.random.seed(42)
hr = pd.DataFrame({
    'heart_rate': np.random.normal(75, 10, 60).round(0)
}, index=pd.date_range('2024-01-15 08:00', periods=60, freq='30s'))
TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e siga alongado. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

(2) A Solução: rolling com Múltiplas Agregações

▶ Exemplo: Estatísticas Múltiplas com rolling (Dificuldade ⭐)

PYTHON
import pandas as pd
import numpy as np

np.random.seed(42)
hr = pd.DataFrame({
    'heart_rate': np.random.normal(75, 10, 60).round(0)
}, index=pd.date_range('2024-01-15 08:00', periods=60, freq='30s'))

# Rolling with multiple aggregations
stats = hr['heart_rate'].rolling(10).agg(['mean', 'std', 'min', 'max'])
stats.columns = ['hr_ma', 'hr_std', 'hr_min', 'hr_max']
print(stats.dropna().head(5).round(1))
TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e siga alongado. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

3. Rolling Avançado

(1) Parâmetros-Chave

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

: Referência do Parâmetro rolling (Dificuldade ⭐⭐)

PYTHON
import pandas as pd
import numpy as np

np.random.seed(42)
s = pd.Series(np.random.randn(20).cumsum() + 100)

# min_periods: allow partial windows
print(s.rolling(5, min_periods=2).mean().head(5))

# center: centered window (for smoothing)
print(s.rolling(5, center=True).mean().head(5))

# win_type: weighted window (Gaussian, triangular, etc.)
print(s.rolling(5, win_type='gaussian').mean(std=1.5).head(8))

# on: use a column as time (when not the index)
df = pd.DataFrame({
    'timestamp': pd.date_range('2024-01', periods=20, freq='6h'),
    'value': np.random.randn(20).cumsum()
})
print(df.rolling('12h', on='timestamp')['value'].mean().head(5))
TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

(2) Referência Rápida dos Parâmetros do rolling

Parâmetro Padrão Descrição
window Obrigatório Tamanho da janela (contagem de linhas inteira ou string de tempo)
min_periods window Número mínimo de observações necessárias na janela
center False Centralizar a janela
win_type None Tipo de ponderação (gaussian/triangular, etc.)
on None Usar uma coluna como eixo do tempo (em vez do Índice)
closed 'right' Qual extremidade da janela é inclusiva

4. Agregação de Janela Personalizada

▶ Exemplo

TEXT 📖 Somente leitura
> **Output:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado. Por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

: Funções de Agregação Personalizadas (Dificuldade ⭐⭐⭐)

PYTHON
import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame({
    'value': np.random.randint(10, 100, 20)
})

# Personalizado: faixa (max - min) na janela
def window_range(arr):
    return arr.max() - arr.min()

df['rolling_range'] = df['value'].rolling(5).apply(window_range, raw=True)

# Personalizado: coeficiente de variação (std/mean)
def cv(arr):
    return arr.std() / arr.mean() if arr.mean() != 0 else 0

df['rolling_cv'] = df['value'].rolling(5).apply(cv, raw=True)

# Usando rolling.apply com raw=True para desempenho
# raw=True: recebe array numpy (rápido)
# raw=False: recebe Series (lento, mas flexível)

print(df.head(10))
TEXT 📖 Somente leitura
> **Output:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado. Por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.
💡 Dica: Usar raw=True em funções personalizadas é cerca de 10x mais rápido (recebe um array NumPy em vez de uma Series), mas você perde o acesso às informações do Índice. Use raw=True para cálculos numéricos simples; use raw=False quando precisar do Índice.


5. expanding em Profundidade

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente local de Python (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

: Funções Customizadas de Expanding (Dificuldade ⭐)

PYTHON
import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame({
    'score': np.random.randint(60, 100, 15)
})

# Métodos expanding integrados
df['cummean'] = df['score'].expanding().mean()
df['cumstd'] = df['score'].expanding().std()
df['cummax'] = df['score'].expanding().max()

# Expanding com min_periods
df['cummean_5'] = df['score'].expanding(min_periods=5).mean()

# Customizado: z-score com expanding
def zscore(arr):
    if len(arr) < 2: return np.nan
    return (arr[-1] - arr.mean()) / arr.std()

df['zscore'] = df['score'].expanding().apply(zscore, raw=True)
print(df.round(2).head(10))
TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente local de Python (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

6. Parâmetros do ewm Explicados

(1) As Quatro Relações de Parâmetros

Parâmetro Relação Significado
span com = span - 1 Semelhante a uma SMA de N períodos
com α = 1/(1+com) Centro de massa
halflife α = 1 - 0.5^(1/halflife) Número de períodos para o peso diminuir pela metade
alpha Especificado diretamente Fator de suavização 0<α≤1

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

: Comparação de Parâmetros do ewm (Dificuldade ⭐⭐)

PYTHON
import pandas as pd
import numpy as np

np.random.seed(42)
s = pd.Series(np.random.randn(30).cumsum() + 100)

# Todas estas são equivalentes (aproximadamente)
ewm_span5 = s.ewm(span=5).mean()
ewm_com4 = s.ewm(com=4).mean()          # com = span - 1
ewm_hl3 = s.ewm(halflife=3).mean()      # ponderação diferente
ewm_alpha = s.ewm(alpha=0.333).mean()   # alpha = 2/(span+1)

# Comparação com SMA
sma5 = s.rolling(5).mean()

print("SMA vs EWM (primeiros 10):")
print(pd.DataFrame({
    'value': s, 'SMA_5': sma5, 'EWM_span5': ewm_span5
}).head(10).round(2))

# ewm std (volatilidade)
ewm_std = s.ewm(span=10).std()
print(f"\nDesvio padrão EWM mais recente: {ewm_std.iloc[-1]:.2f}")
TEXT 📖 Somente leitura
> **Saída:** Execute em seu ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

7. groupby + rolling

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute no seu ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

: Janelas Rolantes Dentro de Grupos (Dificuldade ⭐⭐⭐)

PYTHON
import pandas as pd
import numpy as np

# Dados de sensor: múltiplos sensores, cada um com sua própria série temporal
np.random.seed(42)
df = pd.DataFrame({
    'sensor_id': np.repeat(['T01', 'T02', 'T03'], 20),
    'timestamp': list(pd.date_range('2024-01', periods=20, freq='6h')) * 3,
    'temperature': np.random.normal(20, 3, 60).round(1)
})

# Rolagem dentro de cada grupo de sensor
df = df.sort_values(['sensor_id', 'timestamp'])
df['temp_ma'] = df.groupby('sensor_id')['temperature'].transform(
    lambda x: x.rolling(4, min_periods=1).mean()
)

# Alternativa: groupby + rolling (retorna MultiIndex)
result = df.groupby('sensor_id')['temperature'].rolling(4).mean()
print(result.head(12))

# Reiniciar para saída limpa
df['temp_ma2'] = df.groupby('sensor_id')['temperature'].transform(
    lambda x: x.rolling(4).mean().values
)
print(df[df['sensor_id'] == 'T01'].head(6))
TEXT 📖 Somente leitura
> **Saída:** Execute no seu ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado. Por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

8. Exemplo Completo: Análise de Dados de Frequência Cardíaca em Exercícios

(5) ▶ Comparando Três Tipos de Janelas

100%
graph LR
    A[Funções de Janela] --> B[rolling Janela Fixa]
    A --> C[expanding Janela Cumulativa]
    A --> D[ewm Ponderação Exponencial]
    B --> E[Tendências Locais / Média Móvel]
    C --> F[Estatísticas Cumulativas / Do Início Até Agora]
    D --> G[Dados Recentes com Mais Peso / Suavização]
TEXT 📖 Somente leitura
> **Saída:** Execute no seu ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado. Por favor, instale localmente (`pip install pandas`) e siga o exemplo. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute no seu ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado. Por favor, instale localmente (`pip install pandas`) e siga o exemplo. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

: Pipeline Completo de Análise de Janelas (Dificuldade ⭐⭐⭐)

PYTHON
import pandas as pd
import numpy as np

# ============================================
# Exemplo completo: Fitness de frequência cardíaca
# pipeline de análise de janelas
# ============================================

# 1. Gerar dados de treino de 2 horas (1 leitura a cada 30s = 240 linhas)
np.random.seed(42)
timestamps = pd.date_range('2024-01-15 08:00', periods=240, freq='30s')
exercise_type = (['Aquecimento'] * 30 + ['Cardio'] * 90 + ['Musculação'] * 60 + ['Desaquecimento'] * 60)
hr_base = ([70] * 30 + list(np.linspace(70, 140, 90)) + [120] * 60 + list(np.linspace(120, 70, 60)))
heart_rates = [max(50, h + np.random.randn() * 5) for h in hr_base]

df = pd.DataFrame({
    'timestamp': timestamps,
    'exercise': exercise_type,
    'heart_rate': np.round(heart_rates, 0)
})

# 2. Rolling: média móvel de 1 minuto (2 leituras) e 5 minutos (10 leituras)
df['hr_ma_1min'] = df['heart_rate'].rolling(2).mean()
df['hr_ma_5min'] = df['heart_rate'].rolling(10).mean()

# 3. Rolling: variabilidade da frequência cardíaca (desvio padrão em janela de 5 min)
df['hrv'] = df['heart_rate'].rolling(10).std()

# 4. Expanding: média cumulativa
df['cum_avg_hr'] = df['heart_rate'].expanding().mean()

# 5. EWM: tendencia suavizada
df['hr_ewm'] = df['heart_rate'].ewm(span=10).mean()

# 6. Groupby + rolling: por tipo de exercício
df['hr_ma_per_exercise'] = df.groupby('exercise')['heart_rate'].transform(
    lambda x: x.rolling(5, min_periods=1).mean()
)

# 7. Resumo por exercício
print("=== Resumo do Exercício ===")
summary = df.groupby('exercise')['heart_rate'].agg(['mean', 'max', 'min', 'std']).round(1)
print(summary)
TEXT 📖 Somente leitura
> **Saída:** Execute no seu ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado. Por favor, instale localmente (`pip install pandas`) e siga o exemplo. Os valores reais podem variar ligeiramente dependendo da versão do pandas.

❓ Perguntas Frequentes

P O rolling suporta janelas baseadas em tempo?
R Sim — rolling('7D') usa uma janela de calendário de 7 dias, enquanto rolling(7) usa uma janela de 7 linhas. Janelas baseadas em tempo são ideais para dados amostrados de forma não uniforme (pulando fins de semana ou dias faltantes), enquanto janelas baseadas em linhas são adequadas para amostragem uniforme. Janelas baseadas em tempo requerem que o Índice seja um DatetimeIndex, ou você pode especificar uma coluna de tempo com o parâmetro on.
P Qual é o desempenho de funções personalizadas?
R Funções personalizadas são 10-100x mais lentas que agregações embutidas — uma chamada de função Python é feita para cada janela. Dicas de otimização: use raw=True para passar um array NumPy (5-10x mais rápido), e substitua loops Python por operações NumPy. Funções embutidas são implementadas em C, enquanto funções personalizadas passam pelo interpretador Python. Se uma função embutida resolve o problema, evite escrever uma personalizada.
P Qual é a relação entre span/halflife/com do ewm?
R Todos os três são matematicamente equivalentes — apenas formas diferentes de expressar a mesma coisa. span=N se comporta como uma SMA de N períodos, mas com mais peso nos dados recentes; com=span-1 é o centro de massa; halflife é o número de períodos para o peso diminuir pela metade. span é o mais comumente usado (mais intuitivo). α=2/(span+1) é o fator de suavização. Você só precisa especificar um — não há necessidade de definir múltiplos parâmetros ao mesmo tempo.
P O que devo observar com groupby+rolling?
R Dois pontos-chave: ① Sempre ordene com sort_values pela chave do grupo + tempo primeiro, caso contrário a janela pode cruzar grupos; ② transform(lambda x: x.rolling(N).mean()) retorna um resultado com o mesmo comprimento do DataFrame original, enquanto chamar groupby+rolling diretamente retorna um MultiIndex. Para grandes conjuntos de dados, transform é mais conveniente.
P Quais opções de win_type estão disponíveis?
R Todas as funções de janela do scipy.signal.windows: gaussian (ponderação gaussiana), triang (triangular), blackman, hamming, kaiser, entre outras. Requer pip install scipy. win_type aplica pesos aos dados dentro da janela (peso maior no meio, menor nas bordas), produzindo resultados mais suaves que uma janela de peso igual.
P O que o parâmetro closed faz?
R closed controla qual extremidade da janela é inclusiva — 'right' (padrão, inclui a extremidade direita = linha atual), 'left' (inclui a extremidade esquerda), 'both' (ambas as extremidades), 'neither' (nenhuma das extremidades). Em finanças, 'right' é comumente usado (apenas dados históricos), enquanto certos cenários estatísticos requerem 'both' ou 'left'.

📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Crie 30 dias de dados de temperatura. Use rolling(7, min_periods=3) para calcular a média móvel e o desvio padrão, e use ewm(span=7) para calcular a suavização exponencial.
  2. Intermediário (Dificuldade ⭐⭐): Crie dados de temperatura de múltiplos sensores (3 sensores, 20 linhas cada). Use groupby+rolling para calcular uma média móvel de 5 períodos para cada sensor.
  3. Desafio (Dificuldade ⭐⭐⭐): Simule 240 linhas de dados de frequência cardíaca durante exercícios (com 4 tipos de exercício). Complete o seguinte pipeline: rolling com múltiplas métricas (média/desvio/máximo) → média cumulativa expansiva → suavização ewm → groupby+rolling por tipo de exercício → relatório resumido.

← Previous Lesson: MultiIndex · Next Lesson: Visualization →

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%