Как упростить код в R (тест нормальности): разные размеры выборки в 1 строку или 2 строки кода? - PullRequest
0 голосов
/ 15 марта 2020

Я хочу провести тестирование нормальности в моем коде немного чище и провести симуляцию (повторите тест 1000 раз).

sample <- c(10,30,50,100,500)
shapiro.test(rnorm(sample))

    Shapiro-Wilk normality test

data:  rnorm(sample)
W = 0.90644, p-value = 0.4465

Это дает только один выход, как вы можете наблюдать выше. Как мне получить 5 выходов? Есть что-то, чего я здесь не хватает ..?

Использование функции репликации дает мне 1000 статистик на размер выборки, в то время как меня интересуют только p-значения и они связаны с уровнем значимости. При кодировании отдельных тестов нормальности я использовал следующий код (спасибо пользователю StupidWolf, в моих предыдущих опубликованных вопросах о stackoverflow)

replicate_sw10 = replicate(1000,shapiro.test(rnorm(10)))
table(replicate_sw10["p.value",]<0.10)/1000
#which gave the following output
> FALSE  TRUE 
> 0.896 0.104

Ответы [ 2 ]

2 голосов
/ 15 марта 2020

Вы можете просто использовать $p.value. Приведенный ниже код выдает матрицу с 1000 строк для повторений и 5 столбцами для размеров smpl. Если вы хотите получить список в качестве результата, просто используйте lapply вместо sapply.

smpl <- c(10, 30, 50, 100, 500)

set.seed(42)  ## for sake of reproducibility

res <- sapply(smpl, function(x) replicate(1e3, shapiro.test(rnorm(x))$p.value))
head(res)
#            [,1]      [,2]       [,3]      [,4]      [,5]
# [1,] 0.43524553 0.5624891 0.02116901 0.8972087 0.8010757
# [2,] 0.67500688 0.1417968 0.03722656 0.7614192 0.7559309
# [3,] 0.52777713 0.6728819 0.67880178 0.1455375 0.7734797
# [4,] 0.55618980 0.1736095 0.69879316 0.4950400 0.5181642
# [5,] 0.93774782 0.9077292 0.58930787 0.2687687 0.8435223
# [6,] 0.01444456 0.1214157 0.07042380 0.4479121 0.7982574
2 голосов
/ 15 марта 2020

с использованием пакета purrr

map(sample, function(x) shapiro.test(rnorm(x)))

, что дает

[[1]]

    Shapiro-Wilk normality test

data:  rnorm(x)
W = 0.92567, p-value = 0.4067


[[2]]

    Shapiro-Wilk normality test

data:  rnorm(x)
W = 0.95621, p-value = 0.247


[[3]]

    Shapiro-Wilk normality test

data:  rnorm(x)
W = 0.96144, p-value = 0.1021


[[4]]

    Shapiro-Wilk normality test

data:  rnorm(x)
W = 0.98654, p-value = 0.4077


[[5]]

    Shapiro-Wilk normality test

data:  rnorm(x)
W = 0.99597, p-value = 0.2324

Редактировать: поэтому после редактирования вы запрашиваете какую-то таблицу. Это не работает так, как вы делаете это с вашим примером replicate_sw10, так как это матрица, в то время как map (или, к счастью, неудачно) приводит к списку. Итак, снова вы хотите использовать apply или map для выполнения одинаковых преобразований во всех частях списка.

replicate_swall  <- map(sample, function(x) shapiro.test(rnorm(x)))

replicate_pvalue_extract <- map(replicate_swall  , function(x) x["p.value",]) %>% unlist(., recursive = F)

table(replicate_pvalue_extract  < 0.10) / length(replicate_pvalue_extract )

Это даст вам:

FALSE  TRUE 
0.896 0.104 

Другой вариант - использовать пакет magrittr для извлечения. Ваш код будет выглядеть следующим образом:

replicate_pvalue_extract <- map(replicate_swall, magrittr::extract, "p.value") %>% unlist(., recursive = F)

table(replicate_pvalue_extract  < 0.10) / length(replicate_pvalue_extract )

В приведенном выше коде я предполагал, что вы хотите разделить вашу таблицу на все реплики и что не имеет значения, какой был ввод (с вводом я имею в виду 10,30). 50 100 или 500). Если вам небезразличны входные данные, вы можете хранить их отдельно, я приведу код ниже. Также обратите внимание, что я использовал длину, а не твёрдо закодированный / 1000. Таким образом, ваш код будет более универсальным c, если вы измените номер реплики, то число, на которое вы делите таблицу, также автоматически изменится. В противном случае вам придется вносить изменения в нескольких местах (особенно если кто-то другой использует ваш код), что может легко привести к ошибкам.

replicate_pvalue_extract <- map(replicate_swall  , function(x) x["p.value",]) 

map(replicate_pvalue_extract  , function(x) table(x < 0.10) / length(x))

Или вы можете объединить их:

map(map(replicate_swall, function(x) x["p.value",]), function(x) table(x < 0.10) / length(x))

Вот почему я дал вам опцию magrittr, поскольку мне не нравится функция (x) дважды. С magrittr это будет выглядеть так:

map(map(replicate_swall, magrittr::extract, "p.value"), function(x) table(x < 0.10) / length(x))

, что приведет к:

[[1]]

FALSE  TRUE 
0.896 0.104 

[[2]]

FALSE  TRUE 
0.889 0.111 

[[3]]

FALSE  TRUE 
0.904 0.096 

[[4]]

FALSE  TRUE 
  0.9   0.1 

[[5]]

FALSE  TRUE 
0.891 0.109 
...