Rich Scriven
Rich Scriven

Reputation: 99331

Using a vector's print method in a data frame

Consider the following vector x

x <- c(6e+06, 75000400, 743450000, 340000, 4300000)

I wish to print x in millions, so I wrote a print method and assign a class to x

print.million <- function(x, ...) {
    x <- paste0(round(x / 1e6, 1), "M")
    NextMethod(x, quote = FALSE, ...)
}

class(x) <- "million"

So now x will print how I'd like, with the numeric values also remaining intact.

x
# [1] 6M     75M    743.5M 0.3M   4.3M  
unclass(x)
# [1]   6000000  75000400 743450000    340000   4300000

Here's the problem I'd like to solve. When I go to put x into a data frame, the print method no longer applies, and the numeric values of x are printed normally.

(df <- data.frame(x = I(x)))
#           x
# 1     6e+06
# 2  75000400
# 3 743450000
# 4    340000
# 5   4300000

The class of the x column is still class "million", which is definitely what I want.

df$x
# [1] 6M     75M    743.5M 0.3M   4.3M  
class(df$x)
# [1] "AsIs"    "million"

How can I put x into a data frame and also maintain its print method? I've tried all the arguments to data.frame() and don't really know where to turn next.

The desired result is the data frame below, where x is still class "million", it maintains its underlying numeric values, and also prints in the data frame as it would when it is a vector printed in the console.

#        x
# 1     6M
# 2    75M
# 3 743.5M
# 4   0.3M
# 5   4.3M

Note: This question relates to the second part of an answer I posted earlier.

Upvotes: 5

Views: 620

Answers (1)

Jthorpe
Jthorpe

Reputation: 10167

you need a format method and an as.data.frame method, like these:

x <- c(6e+06, 75000400, 743450000, 340000, 4300000)
class(x) <- 'million'
format.million <- function(x,...)paste0(round(unclass(x) / 1e6, 1), "M")
as.data.frame.million <- base:::as.data.frame.factor
data.frame(x)

Upvotes: 6

Related Questions