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.







