如何编写一个将输出作为S3类返回的函数

时间:2014-11-13 12:42:19

标签: r class methods

我是R的新手,我很难理解如何为函数返回S3类的输出。我有一些文本,我需要为它编写一个汇总方法,它将计算文本中的单词数和文本中前3个单词的频率。我有一个功能计数字,将计算单词。文本在代码上方:

 text = 'The time of year was spring the sun shone for the birds who were not singing yet. The Local farmer was out in the fields preparing for the summer ahead. He had a spring in his step, for he was whistling.'

    #counts the number of words in the text
    countwords = function(x) {
      # Read in the words from the text and separate into a vector
      txt = unlist(strsplit(x,' '))
      # Loop through each word
      k = 0
      for(i in 1:length(txt)) {
        k = k + 1
      }

      return(k)
    }
    countwords(firstpar)

如何将此输出作为s3类返回?如何编写摘要方法/功能?计算文字中的单词和前三个单词?我是R的新手,需要一些帮助来解释S3类,方法和函数。函数是否与方法相同?

谢谢

2 个答案:

答案 0 :(得分:4)

这是执行这两项操作的一种方法,它说明了添加类的方法,而不必编写该类可能需要的所有方法。我还调整了你的函数以提高效率,并将字符串向量作为输入。您也不需要return()电话; IIRC明确地调用return但使用R自动返回函数中最终语句的结果这一事实略微提高效率。

mystring <- "The time of year was spring the sun shone for the birds who were not singing yet. The Local farmer was out in the fields preparing for the summer ahead. He had a spring in his step, for he was whistling."

# counts the number of words in the text
countwords <- function(x) {
  # Read in the words from the text and separate into a vector
  txt <- strsplit(x, " ")
  n <- sapply(txt, length)
  top3 <- lapply(txt, function(x) names(tail(sort(table(x)), 3)))
  out <- list(n = n, top3 = top3)
  class(out) <- c("mysummary", "list")
  out # implied that we return out here
}

countwords(mystring)

这让我们:

> countwords(mystring)
$n
[1] 41

$top3
$top3[[1]]
[1] "for" "was" "the"


attr(,"class")
[1] "mysummary" "list"

哪个不漂亮,但我们稍后可以使用print方法对其进行排序。请注意,这只是一个列表,因此我使用class(out) <- c("mysummary", "list")作为我的S3类来表示来自类"list"的继承

> str(countwords(mystring))
List of 2
 $ n   : int 41
 $ top3:List of 1
  ..$ : chr [1:3] "for" "was" "the"
 - attr(*, "class")= chr [1:2] "mysummary" "list"

这意味着我们可以像任何列表一样对其进行子集化,而无需编写这些方法:

> cw <- countwords(mystring)
> cw$n
[1] 41

> cw[[2]]
[[1]]
[1] "for" "was" "the"

这就是你真正需要的S3类。即使您将其粘贴在包装中,这也不会改变。 (你需要做的额外的事情与ytou类的方法有关,我们没有任何这些方法,因为我们从类"list"继承

> inherits(cw, "list")
[1] TRUE

如果您想添加print方法,我们可以这样做:

`print.mysummary` <- function(x, ...) {
  writeLines(strwrap("Number of words:", prefix = "\n"))
  print(x$n, ...)
  writeLines(strwrap("Top 3 Words:", prefix = "\n"))
  print(x$top3, ...)
  invisible(x) 
}

然后产生:

> cw

Number of words:
[1] 41

Top 3 Words:
[[1]]
[1] "for" "was" "the"

答案 1 :(得分:0)

让@ Roland的评论更加明确:

首先,您要创建自己的S3类,我们将其称为myTextClass,然后分配对象class的{​​{1}}属性。

text

此时,班级class(text)<-c('myTextClass') 并没有为我们做太多事情,所以我们需要为这个班级制作一个方法。特别是,我们将为myTextClass函数创建一个新方法,以便每当summary遇到类summary的对象时,它将执行我们想要的方法而不是任何其他方法。

myTextClass

此方法会执行您提到的一些基本操作,例如字数统计等。现在,当我们在类summary.myTextClass<-function(t){ z1<- paste('Length of text is ', length(unlist(strsplit(t,' '))) ,sep=' ') tb<-table(unlist(strsplit(t,' '))) topWords<-paste(names(tb)[1:3],tb[1:3],sep=':') z2<- paste(c('Top words are... ', topWords) ,collapse=' ') return(c(z1,z2)) } 的对象上调用泛型函数summary时,将调用此特定方法。

myTextClass