简体   繁体   中英

How customize a plot inside a R function which belong to a package?

I'm preparing a small r-package and I would like to use the function plot() on an object created through a function, and getting a customized plot. For instance, this is a very silly example function:

myfun <- function(x,y){

A <- B <- c()

  for(i in 1:x) {
    A[i] <- i^2
    B[i] <- i^2+1}

  return(list(A,B))
}

Then, I create a list with 2 vectors:

obj <- myfun(5,6)

So, the standard approach to get a plot would be:

plot(x=obj[[1]],y=obj[[2]], main='my title',type = 'b', col='red)

BUT, instead of that, I would like to run the following:

plot(obj)

And get the same. So I don't know how to code that into my function in order to get a completely personalize plot. Also, I would like to get a customized summary table, for instance, running the following:

summary(obj)

Be able to get a table with means, sd, etc. I was looking all over StackOverflow about this, with no success, but maybe I used the wrong keywords. Thanks a lot in advance.

If you give your myfun ouput a custom class:

class(obj) <- 'myClass'

Then add a new s3 method:

plot.myClass <- function(obj) {
      plot(x=obj[[1]],y=obj[[2]], main='my title',type = 'b', col='red)
}

Now you can use:

plot(obj)

The answer by SmokeyShakers about plotting is correct, but for your other question about being able to get a table with means, sd, etc. You need to convert your obj to a data frame and then run summary, to be able to get all that stats.

summary(data.frame(x=obj[[1]],y=obj[[2]]))

       x            y     
 Min.   : 1   Min.   : 2  
 1st Qu.: 4   1st Qu.: 5  
 Median : 9   Median :10  
 Mean   :11   Mean   :12  
 3rd Qu.:16   3rd Qu.:17  
 Max.   :25   Max.   :26  

Edit: Or to be consistent, you can do the following:

summary.myClass <- function(obj){summary(data.frame(x=obj[[1]],y=obj[[2]]))}
summary(obj)

You need to define a class and then create your own personal method.

plot() and summary() are generic functions. If you type on your console:

methods(plot)
methods(summary)

You will see a lot of methods already do exist.

While if you print plot on your console you will see that:

 plot
 #> function (x, y, ...) 
 #> UseMethod("plot")
 #> <bytecode: 0x2363df0>
 #> <environment: namespace:graphics>

plot calls a function called UseMethod that will look for all the methods available in the namespaces and the global environment related to plot .

Edit your code this way:

myfun <- function(x,y){

  A <- B <- c()

  for(i in 1:x) {
      A[i] <- i^2
      B[i] <- i^2+1}

  structure(class = "myclass", list(A,B))

  }

This way you can create your class. Your function myfun() will always return an object myclass which is a list of two numeric vectors.

Now you can create your own methods. A method should start with the same name of the generic function and be followed by a dot and the name of your class.

plot.myclass <- function(obj, ...){
    plot(x = obj[[1]], y = obj[[2]], main='my title', type = 'b', col = 'red', ...)
}

obj <- myfun(5,6)
plot(obj)

Add ... in case you want to add more features to your plot in the future.

Same stuff for summary . You can to the same for print for example.

PS: I would strongly advice you to use a lapply() , vapply() or a purrr::map_dbl() instead of a for loop on your example. And to go for a neat ggplot instead of plot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM