r 如何保留自定义类的打印方法

jay*_*dee 5 printing r class

我已经定义了一种使用类 test 打印向量的方法:

print.test <- function(x,  ...) {
    x <- formatC(
        as.numeric(x),
        format = "f",
        big.mark = ".",
        decimal.mark = ",",
        digits = 1
        )
    x[x == "NA"] <- "-"
    x[x == "NaN"] <- "-"
    print.default(x)
}
Run Code Online (Sandbox Code Playgroud)

这适用于以下情况

a <- c(1000.11, 2000.22, 3000.33)
class(a) <- c("test", class(a))
print(a)
[1] "1.000,11" "2.000,22" "3.000,33"
Run Code Online (Sandbox Code Playgroud)

这也有效:

round(a)
[1] "1.000,0" "2.000,0" "3.000,0"
Run Code Online (Sandbox Code Playgroud)

这不会:

median(a)
[1] 2000.22
class(median(a))
[1] "numeric"
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:我是否需要为这个类编写一个自定义方法来使用中值,例如,如果是这样,它会是什么样子或者有另一种方式(因为我只是希望这个类以某种格式打印数据) ?

Rui*_*das 3

问题是median.default返回类的对象numeric,因此返回对象的自动打印不会调用您的自定义print方法。
下面将这样做。

median.test <- function(x, na.rm = FALSE, ...){
    y <- NextMethod(x, na.rm = na.rm, ...)
    class(y) <- c("test", class(y))
    y
}

median(a)
#[1] "2.000,2"
Run Code Online (Sandbox Code Playgroud)

至于NA值的处理,我将首先为基本 R 函数定义另一种方法。不是严格需要的,但如果test经常使用类的对象,可以节省一些代码行。

c.test <- function(x, ...){
    y <- NextMethod(x, ...)
    class(y) <- c("test", class(y))
    y
}


b <- c(a, NA)
class(b)
#[1] "test"    "numeric"

median(b)
#[1] "-"

median(b, na.rm = TRUE)
#[1] "2.000,2"
Run Code Online (Sandbox Code Playgroud)

编辑。

下面按照OP在注释中的要求 定义了一个通用函数wMedian、一个默认方法和一个类对象的方法。"currency"

请注意,必须有一个 method print.currency,我没有重新定义它,因为它与上面完全相同print.test。至于其他方法,我借助新函数 使它们变得更简单as.currency

median.currency <- function(x, na.rm = FALSE, ...){
  y <- NextMethod(x, na.rm = na.rm, ...)
  as.currency(y)
}

c.currency <- function(x, ...){
  y <- NextMethod(x, ...)
  as.currency(y)
}

as.currency <- function(x){
  class(x) <- c("currency", class(x))
  x
}

wMedian <- function(x, ...) UseMethod("wMedian")
wMedian.default <- function(x, ...){
    matrixStats::weightedMedian(x, ...)
}

wMedian.currency <- function(x, w = NULL, idxs = NULL, na.rm = FALSE, interpolate = is.null(ties), ties = NULL, ...) {
  y <- NextMethod(x, w = w, idxs = idxs, na.rm = na.rm, interpolate = interpolate, ties = ties, ... ) 
  as.currency(y)
}


set.seed(1)
x <- rnorm(10)
wMedian(x, w = (1:10)/10)
#[1] 0.4084684
wMedian(as.currency(x), w = (1:10)/10)
#[1] "0,4"
Run Code Online (Sandbox Code Playgroud)