Creating nice looking output

ⅰ亾dé卋堺 提交于 2019-12-07 15:16:50

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!