我如何在 R 中编写测试以便它们打印得很好?
How do I program tests in R so that they print nicely?
R
中的统计测试生成列表,但是当您调用测试时,这些列表的打印提供了一个特殊的用户友好结构来协助 reader。要了解我在说什么,请考虑使用 stats
包中的 t.test
函数的示例。
#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 的 follow-up 问题:
"Each" class的数据有打印方法。正如我在回答中概述的那样,print
函数查看 TEST
,因为它是 htest
的 class,它使用 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 source code on GitHub
这个答案是根据其他用户的有用评论和答案汇总而成的,但我想在这里给出一个详细的答案,使事情更加明确,以使那些还不熟悉其中一些问题的用户受益。 t.test
函数创建的对象是全局环境中classhtest
, and this type of object has a special method of printing under the print.htest
设置的对象。该打印方法从列表中提取信息,但以您在问题输出中看到的 user-friendly 方式打印。
如果您想为自己编写的新统计测试复制这种类型的打印,那么您将需要构建新测试,以便它输出一个 htest
对象,其中包含所需的元素的列表,以及所需的 class。这是另一个 answer where a hypothesis test set out in Tarone (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 的列表。在代码中包含命令 class(TEST) <- "htest"
很重要,这样创建的对象就不仅仅是一个常规列表。包含该命令将确保输出对象是正确的 class,因此它将以 user-friendly 方式打印。为了看到这一点,我们可以生成一些数据并应用测试:
#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
这里我们看到我们新创建的 hypothesis-testing 函数为我们提供了与 t.test
具有相似 user-friendly 结构的输出。在此示例中,我们为测试方法和测试元素指定了不同的名称,这些名称在打印时出现在描述性输出中。
R
中的统计测试生成列表,但是当您调用测试时,这些列表的打印提供了一个特殊的用户友好结构来协助 reader。要了解我在说什么,请考虑使用 stats
包中的 t.test
函数的示例。
#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 的 follow-up 问题:
"Each" class的数据有打印方法。正如我在回答中概述的那样,print
函数查看 TEST
,因为它是 htest
的 class,它使用 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 source code on GitHub
这个答案是根据其他用户的有用评论和答案汇总而成的,但我想在这里给出一个详细的答案,使事情更加明确,以使那些还不熟悉其中一些问题的用户受益。 t.test
函数创建的对象是全局环境中classhtest
, and this type of object has a special method of printing under the print.htest
设置的对象。该打印方法从列表中提取信息,但以您在问题输出中看到的 user-friendly 方式打印。
如果您想为自己编写的新统计测试复制这种类型的打印,那么您将需要构建新测试,以便它输出一个 htest
对象,其中包含所需的元素的列表,以及所需的 class。这是另一个 answer where a hypothesis test set out in Tarone (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 的列表。在代码中包含命令 class(TEST) <- "htest"
很重要,这样创建的对象就不仅仅是一个常规列表。包含该命令将确保输出对象是正确的 class,因此它将以 user-friendly 方式打印。为了看到这一点,我们可以生成一些数据并应用测试:
#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
这里我们看到我们新创建的 hypothesis-testing 函数为我们提供了与 t.test
具有相似 user-friendly 结构的输出。在此示例中,我们为测试方法和测试元素指定了不同的名称,这些名称在打印时出现在描述性输出中。