A curtose da amostra é irremediavelmente tendenciosa?

8

Estou observando a curtose de amostra de uma variável aleatória bastante distorcida e os resultados parecem inconsistentes. Para ilustrar o problema, observei a amostra de curtose de um RV log-normal. Em R (que estou aprendendo lentamente):

library(moments); 

samp_size = 2048;
n_trial = 4096;

kvals <- rep(NA,1,n_trial); #preallocate
for (iii in 1:n_trial) {
    kvals[iii] <- kurtosis(exp(rnorm(samp_size)));
}
print(summary(kvals));

O resumo que recebo é

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  11.87   28.66   39.32   59.17   61.70 1302.00 

Segundo a Wikipedia , a curtose para esse RV log-normal deve ser em torno de 114. Claramente a curtose da amostra é tendenciosa.

Ao fazer algumas pesquisas, descobri que a curtose da amostra é tendenciosa para amostras pequenas. Usei o estimador 'G2', conforme fornecido pelo e1071pacote no CRAN, e obtive resultados muito semelhantes para esse tamanho de amostra.

A questão : qual das seguintes opções caracteriza o que está acontecendo:

  1. O erro padrão da curtose da amostra é simplesmente muito grande para este RV (mesmo que a estimativa comum do erro padrão da onda manual seja da ordem ). Como alternativa, usei poucas amostras (2048) neste estudo.1/n
  2. Essas implementações de curtose amostra sofrem de problemas numéricos que podem ser corrigidos pelo ex método de Terriberry (da mesma maneira que o método de Welford dá melhores resultados do que o método ingênuo de variância da amostra).
  3. Eu calculei a curtose populacional incorretamente. (ai)
  4. A curtose da amostra é inerentemente tendenciosa e você nunca pode corrigi-la para tamanhos de amostra tão pequenos.
shabbychef
fonte
Aliás, como sou iniciante em R, gostaria de receber comentários sobre meu código, por mais breves que sejam, sobre aspectos de estilo e substância. Em particular, eu esperava que houvesse uma maneira mais elegante de expressar o loop for.
shabbychef
1
no estilo R, você não precisa ;no final de suas declarações. Você fez o direito de pré-alocar, mas não precisa preencher NA, kvals <- numeric(length = n_trial)seria suficiente. Com rep, você só precisa dos argumentos 1 e 3 da sua chamada (por exemplo rep(NA, 10)). Na forconfiguração do loop, 1:n_trialpode ser perigoso se estiver programando; melhor é seq_along(kvals)ou seq_len(n_trial)neste caso. Por fim, se você não precisar forçar a impressão, solte a print()rodada summary()- você só precisaria se não estivesse trabalhando de maneira interativa com a R. HTH.
Gavin Simpson
obrigado! definitivamente o que eu estava procurando. Eu estava executando isso de um arquivo, então eu precisava do print. Os argumentos repforam certamente errôneos.
shabbychef

Respostas:

6

Há uma correção de viés . Não é enorme. Acredito que a variância amostral da curtose é proporcional ao oitavo (!) Momento central, que pode ser enorme para uma distribuição lognormal. Você precisaria de milhões de tentativas (ou muito mais) em uma simulação para detectar viés, a menos que o CV seja pequeno. (Faça um histograma de kvals para ver como eles são extraordinariamente distorcidos.)

A curtose correta é realmente sobre 113.9364.

No que diz respeito ao estilo R, pode ser conveniente encapsular a simulação em uma função para que você possa modificar facilmente o tamanho da amostra ou o número de tentativas.

whuber
fonte
2
O estimador G2 de e1071fornece a correção de viés 'padrão'; consulte cran.r-project.org/web/packages/e1071/e1071.pdf . O uso desse estimador em vez de g2, implementado pelo momentspacote, teve pouco efeito, como observei no Q. A dependência no oitavo momento implicaria de fato que o tamanho da amostra é muito pequeno aqui.
shabbychef
5

[Apenas no estilo R - @whuber respondeu à Kurtsosis Q]

Isso foi um pouco complicado demais para ser comentado. Para loops tão simples como o que você usa, podemos combinar a sugestão do @ whuber de encapsular a simulação em uma função com a replicate()função replicate()cuida da alocação e executa o loop para você. Um exemplo é dado abaixo:

require(moments)
foo <- function(size, trials, meanlog = 0, sdlog = 1) {
    replicate(trials,
              kurtosis(rlnorm(size, meanlog = meanlog, 
                              sdlog = sdlog)))
}

Usamos assim:

> set.seed(1)
> out <- foo(2048, 10000)
> summary(out)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.93   28.77   39.99   62.53   62.58 1557.00

Observe que eu uso a rlnorm()função para gerar a variável aleatória log-normal. É equivalente ao exp(rnorm())seu loop, mas usa a ferramenta correta, e permitimos que nossa função repasse parâmetros especificados pelo usuário da distribuição log-normal.

> set.seed(123)
> exp(rnorm(1))
[1] 0.5709374
> set.seed(123)
> rlnorm(1)
[1] 0.5709374
Gavin Simpson
fonte
+1 para set.seed, o que ajudaria em exemplos como este. Existe uma razão substancial para encapsular uma função ( por exemplo, o intérprete R pré-compila funções, portanto, existe alguma aceleração) ou é estilístico ( por exemplo , funções encapsuladoras, como brócolis, são boas para você) ou em algum lugar intermediário ( por exemplo, existem, digamos, muitos operadores em R que atuam em funções; portanto, deve-se acostumar à programação funcional)?
shabbychef
@shabbychef: Eu acho que o principal é o esforço. Você pode executar seu código com o loop etc repetidamente e seria bom, mas você deve continuar executando todas as linhas do seu código. Ao encapsulá-lo, você executa 1 linha de código R para cada simulação que deseja executar. Não há velocidade, pois o R não compila nada antes do tempo IIRC.
Gavin Simpson
1
obrigado pelo esclarecimento. Uma vez que este é tudo em um arquivo pequeno, é uma linha de qualquer maneira: source('foo.r');)
shabbychef