Статистические тесты в R
генерируют списки, но затем, когда вы вызываете тест, печать этих списков дает специальную удобную структуру, чтобы помочь читателю. Чтобы понять, о чем я говорю, рассмотрим пример, в котором вы используете функцию t.test
в пакете stats
.
#Run a T-test on some example data
X <- c(30, 32, 40, 28, 29, 35, 30, 34, 31, 39);
Y <- c(19, 20, 44, 45, 8, 29, 26, 59, 35, 50);
TEST <- stats::t.test(X,Y);
#Show structure of the TEST object
str(TEST);
List of 9
$ statistic : Named num -0.134
..- attr(*, "names")= chr "t"
$ parameter : Named num 10.2
..- attr(*, "names")= chr "df"
$ p.value : num 0.896
$ conf.int : num [1:2] -12.3 10.9
..- attr(*, "conf.level")= num 0.95
$ estimate : Named num [1:2] 32.8 33.5
..- attr(*, "names")= chr [1:2] "mean of x" "mean of y"
$ null.value : Named num 0
..- attr(*, "names")= chr "difference in means"
$ alternative: chr "two.sided"
$ method : chr "Welch Two Sample t-test"
$ data.name : chr "X and Y"
- attr(*, "class")= chr "htest"
Этот объект представляет собой список из девяти элементов, некоторые из которых названы через атрибуты. Однако, когда я печатаю объект TEST
, возвращаемая информация структурируется иначе, чем при стандартной печати списка.
#Print the TEST object
TEST;
Welch Two Sample t-test
data: X and Y
t = -0.13444, df = 10.204, p-value = 0.8957
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-12.27046 10.87046
sample estimates:
mean of x mean of y
32.8 33.5
Как видите, этот вывод на печать намного удобнее для пользователя, чем стандартный вывод списка. Я хотел бы иметь возможность программировать статистические тесты в R
, которые генерируют список выходных данных, подобных приведенному выше, но которые печатаются таким удобным для пользователя способом.
Мои вопросы: Почему R
выводит вывод списка TEST
таким особым образом? Если я создам список выходных данных статистического теста (например, как показано выше), как я могу настроить объект для печати таким образом?
Используйте один из приведенных ниже методов, который лучше всего соответствует вашим потребностям.
X <- c(30, 32, 40, 28, 29, 35, 30, 34, 31, 39)
Y <- c(19, 20, 44, 45, 8, 29, 26, 59, 35, 50)
TEST <- stats::t.test(X,Y)
#default; printing data of htest class
print(TEST)
#printing every element of the list
lapply(TEST, print)
print.listof(TEST)
#printing the results as a dataframe
broom::tidy(TEST) #output of this one is included just for illustration
# A tibble: 1 x 10
estimate estimate1 estimate2 statistic p.value parameter conf.low conf.high method alternative
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 -0.7 32.8 33.5 -0.134 0.896 10.2 -12.3 10.9 Welch Two Sample t-test two.sided
Чтобы ответить на последующий вопрос OP:
Класс данных "Каждый" имеет метод печати. Как я указал в своем ответе, функция print
смотрит на TEST
и, поскольку это класс htest
, она использует print.htest
.
class(TEST)
# [1] "htest"
head(methods(print))
# [1] "print.acf" "print.AES" "print.all_vars" "print.anova"
# [5] "print.anova.lme" "print.ansi_string"
В моем только что открытом сеансе R у меня есть 185 различных методов. По мере загрузки библиотек это число будет увеличиваться.
Если вы хотите копнуть глубже, вам нужно посмотреть исходный код print
, который можно найти здесь: Исходный код R на GitHub
Спасибо за Ваш ответ. Хотя это, безусловно, очень интересно, это не объясняет, почему R
печатает Т-тест так, как он это делает по умолчанию, или как это можно эмулировать в другом списке.
@ Бен Так и есть. «Каждый» класс данных имеет метод печати. Как я указал в своем ответе, print
смотрит на TEST
и, поскольку это класс htest
, он использует print.htest
. Вы можете проверить класс ваших данных class(TEST)
и увидеть различные способы печати methods(print)
. Если вы хотите копнуть глубже, вам нужно посмотреть исходный код print
, который можно найти здесь: github.com/wch/r-source/blob/trunk/src/library/base/R/print.R
Этот ответ составлен из полезных комментариев и ответов других пользователей, но я хотел дать здесь развернутый ответ, чтобы сделать вещи более четкими, для пользователей, которые еще не знакомы с некоторыми из этих вопросов. Объект, созданный функцией t.test
, является объектом класса htest
, и этот тип объекта имеет специальный метод печати в соответствии с настройкой print.htest
в глобальной среде. Этот метод печати извлекает информацию из списка, но печатает ее в удобном для пользователя виде, который вы видите в выводе вопроса.
Если вы хотите воспроизвести этот тип печати для нового статистического теста, который вы программируете самостоятельно, вам нужно будет структурировать свой новый тест так, чтобы он выводил объект htest
с требуемыми элементами списка и требуемым классом. Вот пример из другого отвечать, где проверка гипотезы, изложенная в Тароне (1979), запрограммирована как объект htest
:
Tarone.test <- function(N, M) {
#Check validity of inputs
if (any(M > N)) { stop("Error: Observed count value exceeds binomial trials"); }
#Set hypothesis test objects
method <- "Tarone's Z test";
alternative <- "greater";
null.value <- 0;
attr(null.value, "names") <- "dispersion parameter";
data.name <- paste0(deparse(substitute(M)), " successes from ",
deparse(substitute(N)), " counts");
#Calculate test statistics
estimate <- sum(M)/sum(N);
attr(estimate, "names") <- "proportion parameter";
S <- sum((M - N*estimate)^2/(estimate*(1 - estimate)));
statistic <- (S - sum(N))/sqrt(2*sum(N*(N-1)));
attr(statistic, "names") <- "z";
p.value <- 2*pnorm(-abs(statistic), 0, 1);
attr(p.value, "names") <- NULL;
#Create htest object
TEST <- list(statistic = statistic, p.value = p.value, estimate = estimate,
null.value = null.value, alternative = alternative,
method = method, data.name = data.name);
class(TEST) <- "htest";
TEST; }
В этом примере функция вычисляет все необходимые элементы объекта htest
, а затем создает этот объект в виде списка с этим классом. Важно включить в код команду class(TEST) <- "htest"
, чтобы созданный объект был не просто обычным списком. Включение этой команды гарантирует, что выходной объект имеет надлежащий класс, и поэтому он будет печататься удобным для пользователя способом. Чтобы увидеть это, мы можем сгенерировать некоторые данные и применить тест:
#Generate example data
N <- c(30, 32, 40, 28, 29, 35, 30, 34, 31, 39);
M <- c( 9, 10, 22, 15, 8, 19, 16, 19, 15, 10);
#Apply Tarone's test to the example data
TEST <- Tarone.test(N, M);
TEST;
Tarone's Z test
data: M successes from N counts
z = 2.5988, p-value = 0.009355
alternative hypothesis: true dispersion parameter is greater than 0
sample estimates:
proportion parameter
0.4359756
Здесь мы видим, что наша недавно созданная функция проверки гипотез дает нам выходные данные, которые имеют удобную для пользователя структуру, похожую на t.test
. В этом примере мы дали разные имена методу тестирования и элементам теста, и они появляются в описательных выводах при печати.
Это не мой минус, но я понимаю, почему это так. Вы делаете так называемый пользовательский тест (MY.TEST
), который имеет точные переменные (выходные данные), такие как t.test
. Разве ты не видишь? Вы только что снова создали t.test
, но теперь вместо того, чтобы создавать структуру вывода автоматически, вы помещаете их в htest
вручную. Какой в этом смысл? Если вы можете придумать статистический тест, который впоследствии может быть использован в качестве входных данных для вашей функции, не могли бы вы представить его в качестве примера в своем ответе, чтобы избежать дальнейших отрицательных голосов. Честно говоря, я вывернул свою руку, чтобы не нажать на эту стрелку вниз. Ваше здоровье.
Ему не обязательно иметь те же выходные переменные, что и t.test
. Это может быть совершенно другая проверка гипотезы. Я уже приводил пример другого теста по указанной ссылке (дал опять здесь). Смысл в том, чтобы позволить вам создать тест гипотезы другого типа, но при этом оформить его как объект htest
, чтобы он хорошо печатался. (Эти выходные данные являются обязательными для объекта htest
. Они не являются специфическими для t.test
.)
Что ж, я бы включил часть информации из ссылки, которой вы снова поделились со мной, в вопрос (не в виде ссылки), чтобы люди, которые спешат к концу своего дня, получили больше информации;)
Посмотрите на класс результата, а затем на «методы (печать)».