statistics.kde_random: gere amostras de uma KDE

Publicado em: 13/10/2026
Tempo de leitura: 6 minutos
Visualização de dados e distribuição estatística para statistics.kde_random no Python

statistics.kde_random permite gerar valores aleatórios a partir de uma distribuição estimada com kernel density estimation (KDE). Em vez de assumir que os dados seguem uma distribuição normal, uniforme ou exponencial, você pode partir de uma amostra real e construir uma aproximação suave da densidade observada. Isso é útil em simulações, testes, geração de dados sintéticos, análise exploratória e prototipagem estatística.

O recurso complementa statistics.kde: primeiro você cria uma função de densidade estimada e, em seguida, obtém uma função capaz de produzir novos valores com comportamento parecido ao da amostra original. O ponto central é entender que o resultado depende fortemente da qualidade dos dados, do tamanho da amostra e do parâmetro de suavização.

O que é uma estimativa por kernel

Uma KDE representa cada observação como uma pequena curva, chamada kernel, e soma todas essas curvas para formar uma densidade contínua. O parâmetro de largura de banda controla quanto cada observação influencia os valores próximos. Uma largura muito pequena gera uma densidade cheia de picos; uma largura muito grande pode apagar estruturas importantes, como assimetria ou múltiplos grupos.

Esse modelo não cria informação nova. Ele apenas transforma a amostra em uma aproximação contínua. Portanto, valores extremos, lacunas e vieses presentes nos dados podem aparecer também nas amostras geradas.

Exemplo básico

from statistics import kde, kde_random

dados = [1.2, 1.4, 1.5, 1.8, 2.0, 2.1, 2.2, 2.7, 3.0]
h = 0.25

densidade = kde(dados, h=h)
gerador = kde_random(dados, h=h, seed=42)

amostras = [gerador() for _ in range(10)]
print(amostras)
print(densidade(2.0))

A função retornada por kde_random pode ser chamada repetidamente. Com uma semente fixa, a sequência se torna reproduzível, o que facilita testes automatizados, documentação e comparação de resultados.

Como escolher a largura de banda

A largura de banda, normalmente indicada por h, é a decisão mais importante. Não existe um valor universal. Um bom ponto de partida é comparar vários valores e observar como eles alteram a forma da densidade e as estatísticas das amostras geradas.

Considere um conjunto com dois grupos bem separados. Se h for grande demais, os grupos podem se fundir. Se for pequeno demais, cada observação cria um pico quase isolado. Para dados em escalas diferentes, normalize ou padronize antes de estimar.

from statistics import kde_random, mean, median

base = [10, 11, 11, 12, 13, 20, 21, 22]

for h in (0.3, 1.0, 3.0):
    gerar = kde_random(base, h=h, seed=7)
    simulados = [gerar() for _ in range(5000)]
    print(h, mean(simulados), median(simulados), min(simulados), max(simulados))

Essa comparação ajuda a detectar suavização excessiva e dispersão inesperada. Também é recomendável visualizar histogramas e curvas de densidade quando o ambiente permitir.

Reprodutibilidade com seed

Em ciência de dados, testes e benchmarks, repetir exatamente a mesma sequência pode ser essencial. O argumento seed evita depender do estado global do gerador aleatório. Use sementes fixas em testes e exemplos, mas permita sementes variáveis em simulações que precisam representar múltiplos cenários.

Não confunda reprodutibilidade com segurança. Geradores desse tipo não são adequados para senhas, tokens, chaves ou qualquer uso criptográfico. Para esses casos, use o módulo secrets.

Validação dos dados

Antes de criar o gerador, verifique se a amostra está vazia, contém valores não finitos ou mistura unidades incompatíveis. Uma KDE construída com dados ruins pode produzir resultados plausíveis visualmente, mas estatisticamente enganosos.

from math import isfinite
from statistics import kde_random


def criar_gerador(valores, h, seed=None):
    dados = [float(x) for x in valores]
    if not dados:
        raise ValueError("A amostra não pode ser vazia")
    if h <= 0:
        raise ValueError("h deve ser positivo")
    if not all(isfinite(x) for x in dados):
        raise ValueError("A amostra contém valores não finitos")
    return kde_random(dados, h=h, seed=seed)

Também avalie se existem poucos pontos. Com duas ou três observações, a função pode operar, mas a estimativa dificilmente representa uma população complexa.

Gerando dados sintéticos

Uma aplicação prática é criar dados de teste que preservem aproximadamente a forma da distribuição original sem copiar diretamente cada registro. Isso pode ser útil para protótipos, mas não garante privacidade. Valores gerados podem ficar próximos das observações originais, especialmente com largura pequena. Em dados sensíveis, aplique técnicas específicas de anonimização e privacidade diferencial.

gerar_tempo = criar_gerador([120, 135, 128, 160, 142, 150, 131], h=8, seed=123)
tempos_sinteticos = [round(gerar_tempo(), 2) for _ in range(1000)]

Depois da geração, compare média, mediana, desvio, quantis e proporção de valores fora de limites aceitáveis. Não basta verificar apenas a média.

Controlando limites do domínio

KDEs comuns podem gerar valores fora do domínio natural. Tempos podem sair negativos; proporções podem ultrapassar 1; idades podem ficar abaixo de zero. Você pode rejeitar valores inválidos, transformar os dados antes da estimativa ou escolher outro modelo.

def amostrar_positivo(gerar, tentativas=1000):
    for _ in range(tentativas):
        valor = gerar()
        if valor >= 0:
            return valor
    raise RuntimeError("Não foi possível obter valor válido")

A rejeição é simples, porém pode ser lenta quando grande parte da densidade fica fora do domínio. Para proporções, uma transformação logística pode ser mais adequada.

Testes automatizados

Testes estatísticos não devem esperar uma sequência exata, salvo quando a semente e a implementação são controladas. É melhor verificar propriedades: quantidade de valores, ausência de NaN, limites razoáveis, média aproximada e estabilidade básica.

def test_amostras_kde():
    gerar = criar_gerador([1, 2, 3, 4, 5], h=0.5, seed=10)
    valores = [gerar() for _ in range(2000)]
    assert len(valores) == 2000
    assert all(isfinite(x) for x in valores)
    assert 2.5 < sum(valores) / len(valores) < 3.5

Evite tolerâncias estreitas demais, porque pequenas mudanças internas podem alterar sequências sem tornar o comportamento incorreto.

Desempenho e uso em produção

Para poucas centenas ou milhares de pontos, a abordagem costuma ser prática. Em volumes grandes ou em geração massiva, faça medições. A criação do gerador e cada amostragem possuem custos que podem superar modelos paramétricos simples.

Em sistemas de produção, registre versão do Python, largura de banda, tamanho da amostra e semente quando a rastreabilidade for importante. Não reconstrua o gerador em cada chamada; crie-o uma vez e reutilize.

Quando usar e quando evitar

Use statistics.kde_random quando você tem dados numéricos unidimensionais, quer preservar uma forma não paramétrica e precisa de uma solução da biblioteca padrão. Evite quando a distribuição possui restrições rígidas, quando há poucas observações, quando múltiplas variáveis dependem umas das outras ou quando o objetivo exige garantias formais de privacidade.

Para revisar fundamentos, consulte os guias da Academify sobre ordenação de listas, filas de prioridade com heapq, graphlib e arquivos ZIP seguros. Como fontes externas, use a documentação oficial do módulo statistics e a documentação do módulo random.

Conclusão

statistics.kde_random oferece um caminho direto para amostrar uma densidade aprendida a partir de dados. O recurso é simples de chamar, mas exige decisões cuidadosas sobre largura de banda, domínio, validação e reprodutibilidade. Quando essas etapas são tratadas explicitamente, ele se torna uma ferramenta útil para simulações, testes e exploração estatística sem depender de bibliotecas externas.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Ambiente Linux representando namespaces e automação com os.setns no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    os.setns: entre em namespaces Linux com segurança

    Aprenda os.setns no Python para mover processos entre namespaces Linux com segurança, permissões, testes e limpeza adequada.

    Ler mais

    Tempo de leitura: 5 minutos
    13/10/2026
    Computador com código representando cópia de arquivos com Path.copy no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Path.copy: copie arquivos e pastas com segurança

    Aprenda Path.copy no Python para copiar arquivos e diretórios com controle, segurança, desempenho e compatibilidade.

    Ler mais

    Tempo de leitura: 6 minutos
    12/10/2026
    Código em monitor representando acesso a memória nativa com ctypes.memoryview_at no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ctypes.memoryview_at: acesse memória sem cópias

    Aprenda ctypes.memoryview_at no Python para acessar memória nativa sem cópias, validar ponteiros e evitar erros perigosos.

    Ler mais

    Tempo de leitura: 7 minutos
    12/10/2026
    Código Python em tela representando EnumDict e enumerações avançadas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    EnumDict: personalize Enums com validação

    Aprenda EnumDict no Python para personalizar EnumType, validar membros e criar enumerações avançadas com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    11/10/2026
    Rack de servidores representando balanceamento de conexões com SO_REUSEPORT_LB no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    SO_REUSEPORT_LB: distribua conexões entre workers

    Aprenda SO_REUSEPORT_LB no Python para distribuir conexões entre múltiplos workers com segurança, testes e portabilidade.

    Ler mais

    Tempo de leitura: 6 minutos
    11/10/2026
    Código Python assíncrono em notebook para inspect.markcoroutinefunction
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: identifique wrappers async

    Aprenda inspect.markcoroutinefunction no Python para identificar wrappers assíncronos, integrar frameworks e evitar detecção incorreta de corrotinas.

    Ler mais

    Tempo de leitura: 6 minutos
    10/10/2026