创建漂亮的输出

5
我一直在开发一项雄心勃勃的功能,希望完成后其他人也能使用。当我只是自己使用该函数时,我可以接受输出有些单调乏味,但如果我想要一些漂亮的输出怎么办?我期望的是:
  • 一种在控制台上打印可读内容的方法
  • 能够访问已打印的内容
更具体地说,假设我有三个标量对象需要打印:statdfreepval。目前,我是这样做的:
result <- list(statistic = stat, degrees = dfree, p.value = pval)
return(result)

这样我就可以通过运行函数(名为whites.htest)来访问这些值,例如:

whites.htest$p.value

它可以工作,但输出看起来有点丑陋。

> whites.htest(var.modell)
$statistic
[1] 36.47768

$degrees
[1] 30

$p.value
[1] 0.1928523

如果我们运行一个简单的VAR模型,像这样:

> library(vars)
> data <- matrix(rnorm(200), ncol = 2)
> VAR(data, p = 2, type = "trend")

VAR Estimation Results:
======================= 

Estimated coefficients for equation y1: 
======================================= 
Call:
y1 = y1.l1 + y2.l1 + y1.l2 + y2.l2 + trend 

       y1.l1        y2.l1        y1.l2        y2.l2        trend 
-0.090102007 -0.060138062  0.126250484  0.014423006  0.003138521 


Estimated coefficients for equation y2: 
======================================= 
Call:
y2 = y1.l1 + y2.l1 + y1.l2 + y2.l2 + trend 

       y1.l1        y2.l1        y1.l2        y2.l2        trend 
 0.040118527  0.018274399 -0.132943318 -0.031235939  0.003242241

输出结果非常好。我已经查看了它的基础代码(通过简单运行VAR),但我找不到是什么让它看起来这么好。

所以我的问题是,如何在仍然能够访问函数中的个别对象(即结果)的同时打印出漂亮易读的内容到控制台?


我不认为你的输出有什么丑陋之处。你正在比较两个完全不同的东西,如果你提供一个真正需要的输出示例,并包含样本数据,你可能会得到更好的答案。 - N8TRO
4个回答

7

如果你正在编写更多的函数并想要美化输入的方式(并获得更多的控制),我可以想到一种方法,那就是创建一个类并修改show方法... 大致如下:

# set your class name and its representation is list here.
setClass( "stat_test", representation("list"))


# show method (here's how the output would be printed
# you can format to whatever you want... to show and how to show
setMethod("show", "stat_test", function(object) {
    cat("object of", class(object), "\n")
    cat("Estimated Coefficients\n")
    cat("  statistics\t\t\tdegrees\t\t\tp.value\n")
    cat("  ", object$statistics, "\t\t\t", object$degrees, "\t\t\t", object$p.value,"\n")
})


# now your actual function (here dummy of course)
my_fun <- function(x) {
    t <- list(statistics=1.5, degrees=30, p.value=1e-2)
    new("stat_test", t)
}

# now calling
w <- my_fun(2)
> w # you get

object of stat_test 
Estimated Coefficients
  statistics            degrees         p.value
  1.5            30              0.01 

当然,您需要关注元素的对齐方式。但这只是一个基本的想法。


1
太棒了!非常感谢,这是一个完美的基础代码,可以从中开始扩展。太棒了 :) - hejseb

4
你应该给你的结果命名一个类,例如“resclass”,并创建一个print.resclass函数。 print是一个通用函数,将在函数空间中搜索print.resclass函数,并将其应用于你的对象。你可以使打印方法返回NULL,或者使它以看不见的方式返回对象值。通常的做法是反复调用cat函数。我看到Arun已经提供了一个例子。总是可以从包作者那里学到东西。这是你欣赏的print.varest函数的内容:
 vars:::print.varest
#---------------
function (x, digits = max(3, getOption("digits") - 3), ...) 
{
    dim <- length(x$varresult)
    names <- colnames(x$y)
    text1 <- "VAR Estimation Results:"
    cat(paste("\n", text1, "\n", sep = ""))
    row <- paste(rep("=", nchar(text1)), collapse = "")
    cat(row, "\n")
    cat("\n")
    for (i in 1:dim) {
        result <- coef(x$varresult[[i]])
        text1 <- paste("Estimated coefficients for equation ", 
            names[i], ":", sep = "")
        cat(text1, "\n")
        row <- paste(rep("=", nchar(text1)), collapse = "")
        cat(row, "\n")
        text2 <- paste("Call:\n", names[i], " = ", paste(names(result), 
            collapse = " + "), sep = "")
        cat(text2, "\n\n")
        print(result, ...)
        cat("\n\n")
    }
    invisible(x)
}
<environment: namespace:vars>

谢谢!非常有帮助。我觉得现在我已经掌握了基本思路,知道从哪里开始了。 - hejseb

1
通常的做法是将函数的返回值分配给一个给定的类(你选择类名),然后为该类创建一个打印方法,该方法将以良好的格式输出(通常使用cat),并以不可见的方式返回相同的对象。通常还会有一个摘要方法和一个打印摘要方法来提供额外的输出。
其他有助于美观但容易输出的事情是将想要在屏幕上显示的东西放在矩阵中,并给矩阵行名和列名,然后打印矩阵,打印矩阵函数将负责使事物排列得整齐。一些函数将结合使用cat和打印矩阵。

1

在 @DWin 的回答基础上添加...

# run your example code
library(vars)
data <- matrix(rnorm(200), ncol = 2)
# store the output of `x`
x <- VAR(data, p = 2, type = "trend")

# what kind of object is `x`?
class( x )

# look at code that the author of the `vars`
# package wrote for the print method
getS3method( 'print' , 'varest' )

# look at others..
getS3method( 'print' , 'varsum' )

# ..and others
methods( 'print' )

很好,这解释了一些问题(尤其是现在我可以实际查看varest的输出方式!)。也许是一个愚蠢的问题,但是我如何为我的新类(比如“resclass”)创建一个打印方法呢?假设我想要使用这种方式打印“This is the p-value: <<p.value goes here>>”,而不是简单地使用print(paste("This is the p-value: ", pval, sep=""))。我该怎么做呢? - hejseb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接