[英]Should I use S3 data frames in my package?
I have a package which uses a data.frame based S4 class:我有一个 package,它使用基于 data.frame 的 S4 class:
setClass(Class="foobar",
slots=c(a="character", b="character", c="character"),
contains="data.frame")
Works as intended.按预期工作。 However, I observe weird warnings when combining with tidyverse:但是,在与 tidyverse 结合使用时,我观察到了奇怪的警告:
df <- data.frame(ID=1:5)
df2 <- new("foobar", df)
as_tibble(df2)
The last statement incites a warning message:最后一条语句引发了警告信息:
Warning message:
In class(x) <- c(subclass, tibble_class) :
Setting class(x) to multiple strings ("tbl_df", "tbl", ...); result will no longer be an S4 object
This is because tidyverse does not support S4 data frames .这是因为 tidyverse不支持 S4 数据帧。 This can be circumvented in downstream code by using asS3(df)
.这可以通过使用asS3(df)
在下游代码中规避。 However, users of my package may be puzzled if they see these warnings.但是,如果看到这些警告,我的 package 的用户可能会感到困惑。 I am now faced with the following choices and I don't really know which would be the most reasonable and correct:我现在面临以下选择,我真的不知道哪个是最合理和正确的:
Is there another solution I might be overlooking?还有其他我可能会忽略的解决方案吗?
There is no brilliant solution to this which is entirely within your control.没有完全在您控制范围内的出色解决方案。
The tidyverse
package may call class<-
on any data-frame-like object given to it, and as you have seen this will destroy the S4 nature of any object. tidyverse
package 可以在任何类似数据帧的 object 上调用class<-
,正如您所见,这将破坏任何 object 的 S4 特性。 This can't be worked around by (for instance) defining a method for coerce
or calling setAs
, as class<-
doesn't use that mechanism.这不能通过(例如)定义coerce
方法或调用setAs
,因为class<-
不使用该机制。 ( class<-
isn't generic either, you can't set a method for it.) The only way to make tidyverse
support S4 is for tidyverse
's author to alter the code to use as
or similar, and it doesn't look like that is top of their to-do-list. ( class<-
也不是通用的,你不能为它设置一个方法。)让tidyverse
支持 S4 的唯一方法是让tidyverse
的作者更改代码以使用as
或类似的,它没有看起来那是他们的待办事项清单的首位。
You are correct to be worried about dramatically altering the way your class works when you have released a version of your package already with an S4 class.当您已经发布了带有 S4 class 的 package 版本时,您担心会显着改变 class 的工作方式是正确的。
If:如果:
then it may be best to redefine it as S3, and include a message when your package is installed or loaded to say那么最好将其重新定义为 S3,并在安装或加载 package 时包含一条消息说
thanks for installing myPackage v2.感谢您安装 myPackage v2。 Code may be incompatible with v1.2 or earlier;代码可能与 v1.2 或更早版本不兼容; see help(blah) for details有关详细信息,请参阅帮助(等等)
otherwise, stick with S4.否则,坚持使用S4。
You can't exactly mix S3 and S4 for class definitions (you can for method definitions).对于 class 定义,您不能完全混合 S3 和 S4(您可以用于方法定义)。 The closest you can come is setOldClass
which registers a S3 class as an S4 one (whereas you wanted the opposite).最接近您的是setOldClass
,它将 S3 class 注册为 S4 (而您想要相反)。 Still, that may help you achieve "you can do all you need to do with S3" above.不过,这可能会帮助您实现上面的“您可以使用 S3 做所有您需要做的事情”。
One other possibility is to define your own version of class<-
which checks to see if an object of S4 class foobar
is attempting to be coerced to S3
and calls the ordinary class<-
if not.另一种可能性是定义您自己的class<-
版本,它检查 S4 class foobar
的 object 是否试图被强制转换为S3
并调用普通class<-
如果不是。 The cure is probably worse than the disease in this case;在这种情况下,治愈可能比疾病更糟; this will slow down all future S3 class conversions (since class<-
is now an ordinary function call, not a primitive) but it should work in principle.这将减慢所有未来的 S3 class 转换(因为class<-
现在是普通的 function 调用,而不是原语),但原则上应该可以工作。 Another reason that it is not recommended is that you are relying on no other package higher in the search path doing something similar (what if another package author had the same issue and wanted to do the same trick? Then the results would depend on which package was higher up the search
path!)不推荐的另一个原因是您在搜索路径中不依赖其他 package 做类似的事情(如果另一个 package 的作者有同样的问题并想要做同样的伎俩呢?那么结果将取决于哪个 package在search
路径上更高!)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.