R - 设置用 by() 创建的 object 的 class

R - Setting the class of an object created with by()

首先介绍一下上下文:

在我的包 summarytools 中,我为 class 的 objects 定义了一个 print 方法 "summarytools"。我还创建了一个函数 view() 来处理使用 by()lapply() 创建的 objects lapply() 情况下的变量; summarytools 显示它自己的包含该信息的标题,因此在使用 print 时会有一些冗余。此外,使用 view().

时不会重复主标题

这是一个例子。请注意,在此版本(开发中)中,我包含一条消息,建议使用 view():

> library(summarytools)
> (tmp <- with(tobacco, by(smoker, gender, freq)))
gender: F
For best results printing list objects with summarytools, use view(x, method = 'pander')
Frequencies   
tobacco$smoker     
Type: Factor    
Group: gender = M   

              Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
----------- ------ --------- -------------- --------- --------------
        Yes    147     30.06          30.06     30.06          30.06
         No    342     69.94         100.00     69.94         100.00
       <NA>      0                               0.00         100.00
      Total    489    100.00         100.00    100.00         100.00
------------------------------------------------------------------ 
gender: M
Frequencies   
tobacco$smoker     
Type: Factor    
Group: gender = F   

              Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
----------- ------ --------- -------------- --------- --------------
        Yes    143     29.24          29.24     29.24          29.24
         No    346     70.76         100.00     70.76         100.00
       <NA>      0                               0.00         100.00
      Total    489    100.00         100.00    100.00         100.00

现在使用 view():

> view(tmp, method = "pander")
Frequencies   
tobacco$smoker     
Type: Factor    
Group: gender = M   

              Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
----------- ------ --------- -------------- --------- --------------
        Yes    147     30.06          30.06     30.06          30.06
         No    342     69.94         100.00     69.94         100.00
       <NA>      0                               0.00         100.00
      Total    489    100.00         100.00    100.00         100.00

Group: gender = F   

              Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
----------- ------ --------- -------------- --------- --------------
        Yes    143     29.24          29.24     29.24          29.24
         No    346     70.76         100.00     70.76         100.00
       <NA>      0                               0.00         100.00
      Total    489    100.00         100.00    100.00         100.00

我考虑过如何将 class "by" 的 objects 自动分派到 view() 而不是 print()。如果我将 class "summarytools" 添加到那些 objects,print() 方法可以将调用重定向到 view(),使用户更容易获得正确的、最佳的输出。

到目前为止,我想到的解决方案如下:

  1. 向函数添加 "by" 参数,以便我可以完全控制创建的 objects' 属性。我不喜欢这个解决方案,因为 1) 我尝试依赖人们熟悉的基本 R 函数而不是引入新参数,以及 2) 创建 objects 时我仍然有类似的问题lapply().
  2. 重新定义 by(),以便在从 summarytools 的一个函数中调用它时,它会将所需的 class 附加到创建的 objects。我避免了这一点,因为我对重新定义基本函数犹豫不决。我不想看到 objects 在加载包时被屏蔽的消息。
  3. 定义一个package-specificby(),比如by_st();我可以使用与 by.default()by.data.frame() 基本相同的代码,唯一的区别是我将 "summarytools" class 添加到创建的 objects 中。这是我正在考虑的一种妥协。

我的问题如下:是否还有其他我没有看到的更好的解决方案?

您可以使用 print.by 的 S3 方法分派到您的自定义函数:

old.print.by = print.by # save the original function so we can restore it later
print.by = summarytools::view # redefine print.by to dispatch to custom function
tmp

稍后要恢复原始功能,您可以执行 print.by = old.print.by

如果您只想让您的新函数对包含 class "summarytools" 对象的列表进行操作,您可以使用

print.by = function(x, method = 'pander', ...) {
  if ("summarytools" %in% class(x[[1]])) {
    summarytools::view(x, method, ...)
  } else {
    old.print.by(x, ...)
  }
}