Более серьезный ответ на этот вопрос и особенно постоянный интерес @ silverfish. Один из подходов к ответам на подобные вопросы - провести несколько симуляций для сравнения. Ниже приведен некоторый R-код, который моделирует данные при различных альтернативах и выполняет несколько тестов нормальности и сравнивает мощность (и доверительный интервал для мощности, поскольку мощность оценивается посредством моделирования). Я несколько изменил размеры выборки, потому что было неинтересно, когда многие из степеней были близки к 100% или 5%, я нашел круглые числа, которые дали мощности около 80%. Любой желающий может легко взять этот код и изменить его для разных предположений, разных альтернатив и т. Д.
Вы можете видеть, что есть альтернативы, для которых некоторые тесты работают лучше, а другие - хуже. Важным вопросом является то, какие альтернативы являются наиболее реалистичными для ваших научных вопросов / области. Это действительно должно сопровождаться моделированием влияния типов ненормальностей, представляющих интерес, на другие выполняемые тесты. Некоторые из этих типов ненормальностей сильно влияют на другие обычные тесты, другие не сильно влияют на них.
> library(nortest)
>
> simfun1 <- function(fun=function(n) rnorm(n), n=250) {
+ x <- fun(n)
+ c(sw=shapiro.test(x)$p.value, sf=sf.test(x)$p.value, ad=ad.test(x)$p.value,
+ cvm=cvm.test(x)$p.value, lillie=lillie.test(x)$p.value,
+ pearson=pearson.test(x)$p.value, snow=0)
+ }
>
> ### Test size using null hypothesis near true
>
> out1 <- replicate(10000, simfun1())
> apply(out1, 1, function(x) mean(x<=0.05))
sw sf ad cvm lillie pearson snow
0.0490 0.0520 0.0521 0.0509 0.0531 0.0538 1.0000
> apply(out1, 1, function(x) prop.test(sum(x<=0.05),length(x))$conf.int) #$
sw sf ad cvm lillie pearson snow
[1,] 0.04489158 0.04776981 0.04786582 0.04671398 0.04882619 0.04949870 0.9995213
[2,] 0.05345887 0.05657820 0.05668211 0.05543493 0.05772093 0.05844785 1.0000000
>
> ### Test again with mean and sd different
>
> out2 <- replicate(10000, simfun1(fun=function(n) rnorm(n,100,5)))
> apply(out2, 1, function(x) mean(x<=0.05))
sw sf ad cvm lillie pearson snow
0.0482 0.0513 0.0461 0.0477 0.0515 0.0506 1.0000
> apply(out2, 1, function(x) prop.test(sum(x<=0.05),length(x))$conf.int) #$
sw sf ad cvm lillie pearson snow
[1,] 0.04412478 0.04709785 0.04211345 0.04364569 0.04728982 0.04642612 0.9995213
[2,] 0.05262633 0.05585073 0.05043938 0.05210583 0.05605860 0.05512303 1.0000000
>
> #### now for the power under different forms of non-normality
>
> ## heavy tails, t(3)
> rt3 <- function(n) rt(n, df=3)
>
> out3 <- replicate(10000, simfun1(fun=rt3, n=75))
There were 50 or more warnings (use warnings() to see the first 50)
> round(apply(out3, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.788 0.831 0.756 0.726 0.624 0.440 1.000
> round(apply(out3, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.780 0.824 0.748 0.717 0.614 0.431 1
[2,] 0.796 0.838 0.765 0.734 0.633 0.450 1
>
>
> ## light tails, uniform
> u <- function(n) runif(n)
>
> out4 <- replicate(10000, simfun1(fun=u, n=65))
> round(apply(out4, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.906 0.712 0.745 0.591 0.362 0.270 1.000
> round(apply(out4, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.900 0.703 0.737 0.581 0.353 0.261 1
[2,] 0.911 0.720 0.754 0.600 0.372 0.279 1
>
> ## double exponential, Laplace
> de <- function(n) sample(c(-1,1), n, replace=TRUE) * rexp(n)
>
> out5 <- replicate(10000, simfun1(fun=de, n=100))
> round(apply(out5, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.796 0.844 0.824 0.820 0.706 0.477 1.000
> round(apply(out5, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.788 0.837 0.817 0.813 0.697 0.467 1
[2,] 0.804 0.851 0.832 0.828 0.715 0.486 1
>
> ## skewed, gamma(2,2)
> g22 <- function(n) rgamma(n,2,2)
>
> out6 <- replicate(10000, simfun1(fun=g22, n=50))
Warning message:
In cvm.test(x) :
p-value is smaller than 7.37e-10, cannot be computed more accurately
> round(apply(out6, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.954 0.930 0.893 0.835 0.695 0.656 1.000
> round(apply(out6, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.950 0.925 0.886 0.827 0.686 0.646 1
[2,] 0.958 0.935 0.899 0.842 0.704 0.665 1
>
> ## skewed, gamma(2,2)
> g99 <- function(n) rgamma(n,9,9)
>
> out7 <- replicate(10000, simfun1(fun=g99, n=150))
> round(apply(out7, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.844 0.818 0.724 0.651 0.526 0.286 1.000
> round(apply(out7, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.836 0.810 0.715 0.642 0.516 0.277 1
[2,] 0.851 0.826 0.732 0.660 0.536 0.294 1
>
> ## tails normal, middle not
> mid <- function(n) {
+ x <- rnorm(n)
+ x[ x > -0.5 & x < 0.5 ] <- 0
+ x
+ }
>
> out9 <- replicate(10000, simfun1(fun=mid, n=30))
Warning messages:
1: In cvm.test(x) :
p-value is smaller than 7.37e-10, cannot be computed more accurately
2: In cvm.test(x) :
p-value is smaller than 7.37e-10, cannot be computed more accurately
> round(apply(out9, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.374 0.371 0.624 0.739 0.884 0.948 1.000
> round(apply(out9, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.365 0.362 0.614 0.730 0.878 0.943 1
[2,] 0.384 0.381 0.633 0.747 0.890 0.952 1
>
> ## mixture on variance
> mv <- function(n, p=0.1, sd=3) {
+ rnorm(n,0, ifelse(runif(n)<p, sd, 1))
+ }
>
> out10 <- replicate(10000, simfun1(fun=mv, n=100))
Warning message:
In cvm.test(x) :
p-value is smaller than 7.37e-10, cannot be computed more accurately
> round(apply(out10, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.800 0.844 0.682 0.609 0.487 0.287 1.000
> round(apply(out10, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.792 0.837 0.673 0.599 0.477 0.278 1
[2,] 0.808 0.851 0.691 0.619 0.497 0.296 1
>
> ## mixture on mean
> mm <- function(n, p=0.3, mu=2) {
+ rnorm(n, ifelse(runif(n)<p, mu, 0), 1)
+ }
>
> out11 <- replicate(10000, simfun1(fun=mm, n=400))
> round(apply(out11, 1, function(x) mean(x<=0.05, na.rm=TRUE)),3)
sw sf ad cvm lillie pearson snow
0.776 0.710 0.808 0.788 0.669 0.354 1.000
> round(apply(out11, 1, function(x){
+ prop.test(sum(x<=0.05,na.rm=TRUE),sum(!is.na(x)))$conf.int),3) } #$
sw sf ad cvm lillie pearson snow
[1,] 0.768 0.701 0.801 0.780 0.659 0.344 1
[2,] 0.784 0.719 0.816 0.796 0.678 0.363 1