1

I'm experimenting with S3-class methods and generic functions, but I'm having an issue which I think highlights a misunderstanding in my thinking. Perhaps I'm getting confused with how printing works, or how storing values and attributes works internally?

I've tried to google around to no avail, possibly because I'm not too sure what I'm looking for.

Setup

library(data.table)

# trivial data
dt <- CJ(letter = c("A", "B", "C"), number = 1:4)

# -- generic functions
coverage <- function (x, ...) {
  UseMethod("coverage", x)
}

prettyprint <- function (x, ...) {
  UseMethod("prettyprint", x)
}

Class methods

# coverage method to find % of data.table satisfying an expr
coverage.data.table <- function(dt, subset, desc) {
  e <- parse(text = subset)  # parse condition to expression
  coverage <- dt[eval(e), .N]/dt[, .N]  # express coverage as a percent 
  class(coverage) <- c("coverage", class(coverage))  # set as 'coverage' class
  attributes(coverage)[["desc"]] <- desc  # carry description for printing
  coverage
}

# human readable data.table coverage
prettyprint.coverage <- function(coverage) {
  desc <- attributes(coverage)[["desc"]]
  paste0(round(coverage*100, 2), "% ", desc)
}

# normal printing
print.coverage <- function(coverage) {

  # unsure what to put in here such that I can use
  # this value with standard other operations such 
  # as multiplication

}

coverageB <- coverage(dt, "letter == \"B\"", "of data.table is in B")

> coverageB  # prints nothing as expected from empty function
> prettyprint(coverageB)
  [1] "33.33% of data.table is in B"

Printing coverageB without loading print.coverage gives

> coverageB
[1] 0.3333333
attr(,"class")
[1] "coverage" "numeric" 
attr(,"desc")
[1] "of data.table is in B"

where I'd like some way to print just the 0.3333333.

Help would be much appreciated. Thanks.

(As a side note, I'm sure that eval(parse(...)) statement is not the right way to do things. Any pointers there would be appreciated too.)

I also wasn't sure what to title this - if anyone has any more appropriate suggestion I'm happy to change it.

4

1 回答 1

1

这里有两种更好的可能性,第一种遵循您的方法(由于自动索引可能会更快,但我没有进行基准测试):

coverage.data.table <- function(dt, subset, desc) {
  coverage <- dt[eval(substitute(subset)), .N]/dt[, .N]  # express coverage as a percent 
  #coverage <- dt[, mean(eval(substitute(subset)))]  # express coverage as a percent 
  class(coverage) <- c("coverage", class(coverage))  # set as 'coverage' class
  attributes(coverage)[["desc"]] <- desc  # carry description for printing
  coverage
}

然后你这样称呼它:

coverageB <- coverage(dt, letter == "B", "of data.table is in B")

这是一种print用于c删除所有属性的方法(请参阅其文档):

# normal printing
print.coverage <- function(coverage) {
  print.default(c(coverage))
} 

coverageB
#[1] 0.3333333
prettyprint(coverageB)
#[1] "33.33% of data.table is in B"

但是,我不明白您对该print方法的评论。该print方法与乘法无关。

于 2015-11-15T14:21:11.260 回答