Тест Шапиро-Уилка на строку

#r #statistics #normal-distribution

#r #Статистика #нормальное распределение

Вопрос:

Я пытаюсь определить нормальность для значений в строках фрейма данных. В идеале я хочу рассчитать тест Шапиро-Уилка на строку (столько тестов, сколько строк находится во фрейме данных).

Реальный набор данных большой, но для этой цели я использую пример.

 dput(example)
structure(c(103L, 122L, 40L, 107L, 124L, 108L, 89L, 102L, 40L, 
70L, 78L, 78L, 78L, 78L, 64L, 64L, 64L, 50L, 50L, 50L, 133L, 
64L, 55L, 64L, 108L, 124L, 108L, 146L, 13L, 40L, 122L, 124L, 
107L, 122L, 133L, 122L, 107L, 121L, 70L, 113L, NA, 108L, NA, 
40L, 122L, 89L, 36L, 113L, 26L, 26L, NA, 103L, NA, 55L, 153L, 
146L, 36L, NA, NA, 77L, NA, 133L, NA, 36L, 167L, 92L, 65L, NA, 
NA, 40L, NA, 107L, NA, 89L, 146L, NA, 92L, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA), .Dim = 10:9, .Dimnames = list(
    c("7", "10", "51", "62", "4", "5", "79", "16", "17", "243"
    ), c("centroid", "n_1", "n_2", "n_3", "n_4", "n_5", "n_6", 
    "n_7", "n_8")))
  

Как уже было сказано, я хотел бы проверить нормальность для каждой строки, и я предсказываю, что некоторые строки будут «проходить», а для других нормальность не будет рассчитана, потому что недостаточно значений или все они идентичны. Я на самом деле очень заинтересован в этом, поскольку пытаюсь доказать, что это плохая идея.
Я бы хотел, чтобы мои результаты были записаны в новый столбец, и если тест на нормальность не может быть рассчитан, появится сообщение об ошибке (что-то ОШИБКА / ЛОЖЬ)

введите описание изображения здесь

Я могу вычислить Шапиро для любой строки, подобной этой:

 shapiro.test(example[1,])
    Shapiro-Wilk normality test

data:  example[1, ]
W = 0.9631, p-value = 0.7984
  

И я должен иметь возможность вычислять Шапиро на строку следующим образом (не работает):

 > apply(example, example[1:10,], shapiro.test) 
Error in d[-MARGIN] : only 0's may be mixed with negative subscripts
  

Я надеюсь, что кто-то может указать мне правильное направление.
Спасибо!

Ответ №1:

Вы могли бы написать функцию для получения желаемого результата:

 df <- structure(c(103L, 122L, 40L, 107L, 124L, 108L, 89L, 102L, 40L, 
                  70L, 78L, 78L, 78L, 78L, 64L, 64L, 64L, 50L, 50L, 50L, 133L, 
                  64L, 55L, 64L, 108L, 124L, 108L, 146L, 13L, 40L, 122L, 124L, 
                  107L, 122L, 133L, 122L, 107L, 121L, 70L, 113L, NA, 108L, NA, 
                  40L, 122L, 89L, 36L, 113L, 26L, 26L, NA, 103L, NA, 55L, 153L, 
                  146L, 36L, NA, NA, 77L, NA, 133L, NA, 36L, 167L, 92L, 65L, NA, 
                  NA, 40L, NA, 107L, NA, 89L, 146L, NA, 92L, NA, NA, NA, NA, NA, 
                  NA, NA, NA, NA, NA, NA, NA, NA), .Dim = 10:9, .Dimnames = list(
                    c("7", "10", "51", "62", "4", "5", "79", "16", "17", "243"
                    ), c("centroid", "n_1", "n_2", "n_3", "n_4", "n_5", "n_6", 
                         "n_7", "n_8")))

f.shapiro.stat <- function(x, n_diff_numbers = 3) {
  res <- ifelse(sum(!is.na(unique(x))) < n_diff_numbers, 'ERROR', shapiro.test(x)$statistic)
  return(res)
}

res <- apply(df, 1, f.shapiro.stat, n_diff_numbers = 3)

df2 <- as.data.frame(df)
df2$shapiro <- res
df2
> df2
    centroid n_1 n_2 n_3 n_4 n_5 n_6 n_7 n_8   shapiro
7        103  78 133 122  NA  NA  NA  NA  NA 0.9630974
10       122  78  64 124 108 103 133 107  NA 0.9225951
51        40  78  55 107  NA  NA  NA  NA  NA 0.9723459
62       107  78  64 122  40  55  36  89  NA 0.9552869
4        124  64 108 133 122 153 167 146  NA 0.9385053
5        108  64 124 122  89 146  92  NA  NA 0.9809580
79        89  64 108 107  36  36  65  92  NA 0.8915689
16       102  50 146 121 113  NA  NA  NA  NA 0.9307804
17        40  50  13  70  26  NA  NA  NA  NA 0.9911093
243       70  50  40 113  26  77  40  NA  NA 0.9238762
  

Функция также проверяет, достаточно ли вариаций в ваших данных.
Пример:

 > f.shapiro.stat(x = rep(1,1,1))
[1] "ERROR"
  

Комментарии:

1. Спасибо, это действительно работает. Но разве в первой строке не предполагается число вместо NA? shapiro.test(df[1,]) p-value = 0.7984

2. Нет, потому что в первой строке 5 NAS, что больше, чем 4 (что проверяется в функции). Я отредактировал функцию таким образом, что вы получите сообщение об ошибке, если все числа в строке равны.

3. хорошо, я вижу, я забыл объяснить, что NA следует просто игнорировать (биологические данные) Нормальность должна проверяться только в действительных числах в строке. Но поскольку иногда в строке всего 2 числа, это должно привести к ошибке.

4. Если недостающие числа представлены, NA вы можете внести изменения в строку ifelse(sum(is.na(x)) > n_NAs, NA, shapiro.test(x)$statistic) ifelse(sum(is.na(x)) > n_NAs, "ERROR", shapiro.test(x)$statistic) , и вы получите «ОШИБКА» вместо NA.

5. Я только что понял, что печатается W, поэтому я изменил его, чтобы он печатал значение p.значение shapiro.test (x) $ p.значение Еще раз спасибо

Ответ №2:

 apply(example[1:10,], 1, shapiro.test)
  

«1» в середине — это измерение, к которому вы применяете функцию.
1 для строки, 2 для столбца.

Комментарии:

1. вы правы. Спасибо! У меня все еще есть проблемы из-за NA и подобных чисел. Но в этом вы правы. Спасибо!