#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 и подобных чисел. Но в этом вы правы. Спасибо!