5

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.

Community
  • 1
  • 1
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245

1 Answers1

6

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)
Jthorpe
  • 9,756
  • 2
  • 49
  • 64
  • it still is a numeric vector. try `unclass(df$x)` or `df$x + 10^6`. (note that i made a correction in the function) – Jthorpe Jan 27 '15 at 03:25
  • I'm not calling `df <- data.frame(x = format(x))`. it's just that print.data.frame` calls the `format` method to determine how to print the data.frame to the console – Jthorpe Jan 27 '15 at 03:30
  • 1
    if you read `as.data.frame.factor` it's doesn't rely on any of the attributes of factors, and it takes care of everything you need to create a data.frame object from a vector. – Jthorpe Jan 27 '15 at 03:38