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()
,使用户更容易获得正确的、最佳的输出。
到目前为止,我想到的解决方案如下:
- 向函数添加 "by" 参数,以便我可以完全控制创建的 objects' 属性。我不喜欢这个解决方案,因为 1) 我尝试依赖人们熟悉的基本 R 函数而不是引入新参数,以及 2) 创建 objects 时我仍然有类似的问题
lapply()
.
- 重新定义
by()
,以便在从 summarytools 的一个函数中调用它时,它会将所需的 class 附加到创建的 objects。我避免了这一点,因为我对重新定义基本函数犹豫不决。我不想看到 objects 在加载包时被屏蔽的消息。
- 定义一个package-specific
by()
,比如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, ...)
}
}
首先介绍一下上下文:
在我的包 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()
,使用户更容易获得正确的、最佳的输出。
到目前为止,我想到的解决方案如下:
- 向函数添加 "by" 参数,以便我可以完全控制创建的 objects' 属性。我不喜欢这个解决方案,因为 1) 我尝试依赖人们熟悉的基本 R 函数而不是引入新参数,以及 2) 创建 objects 时我仍然有类似的问题
lapply()
. - 重新定义
by()
,以便在从 summarytools 的一个函数中调用它时,它会将所需的 class 附加到创建的 objects。我避免了这一点,因为我对重新定义基本函数犹豫不决。我不想看到 objects 在加载包时被屏蔽的消息。 - 定义一个package-specific
by()
,比如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, ...)
}
}