问题
I've been working on quite an ambitious function, which I hope can be used by people other than me once I am finished. When it's just me using the function I can live with the output being kind of lame, but what if I want some nice looking output? What I'm looking for is essentially this:
- A way of printing something readable to the console
- Being able to access what's printed
More specifically, let's assume I have three scalar objects I want to be printed: stat
, dfree
and pval
. Currently, the way I do it is:
result <- list(statistic = stat, degrees = dfree, p.value = pval)
return(result)
That way I can access these values by running, for example (the function is called whites.htest
):
whites.htest$p.value
It works, but the output is kind of ugly.
> whites.htest(var.modell)
$statistic
[1] 36.47768
$degrees
[1] 30
$p.value
[1] 0.1928523
If we run a simple VAR model like this:
> 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
The output looks really good. I've had a look at the underlying code for it (by simply running VAR
), but I cannot find what makes it look good like this.
So my question is, how do I print something nice and readable to the console while still being able to access individual objects (i.e. results) from the function?
回答1:
One way I could think of to prettify the input (and gain more control if you're writing more functions) is to create a class and modify the show
method.. Something like this:
# 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
You should take care of the alignments of course. But this is one basic idea.
回答2:
You should give your result a class, say "resclass" and create a print.resclass
function. print
is a generic function an will search the function space for print.resclass
and apply it to your object. You can either have the print method return NULL or have it return the object value invisibly. The usual way of doing this is repeated calls to cat
. I see Arun has already provided an example. It's always possible to learn from you package authors. Here's the print.varest
function that you admired:
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>
回答3:
adding to @DWin's answer..
# 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' )
回答4:
The usual practice is to assign the return value from your function to have a given class (you choose the name of the class), then you create a print method for the class which will nicely format the output (often using cat
) and return the same object invisibly. Often there is also a summary method and a print.summary method to give additional output.
Other things to help with nice, but easy, output is to put the things that you want on the screen in a matrix and give the matrix row names and column names, then print the matrix and the print.matrix function will take care of lining things up nicely. Some functions will combine using cat
and printing matrices.
来源:https://stackoverflow.com/questions/15046682/creating-nice-looking-output