简体   繁体   English

我应该在我的 package 中使用 S3 数据帧吗?

[英]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:我现在面临以下选择,我真的不知道哪个是最合理和正确的:

  • Keep the S4 model and hope that the users won't mind seeing this warning each time they pass my data frames into something else.保留 S4 model 并希望用户每次将我的数据帧传递给其他东西时都不会介意看到此警告。
  • Use S3.使用 S3。 However, I already have another S4 class defined in published versions of my package.但是,我的 package 的已发布版本中已经定义了另一个 S4 class。 I am afraid that I would break someones code.我怕我会破坏别人的代码。
  • Mix S3 and S4.混合 S3 和 S4。 Is it even allowed?甚至允许吗?

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:如果:

  • your package is quite new and doesn't yet have many users;您的 package 很新,还没有很多用户;
  • you can do all you need to do with S3;你可以用 S3 做所有你需要做的事情; and
  • you don't know of another package which has built new classes on top of yours你不知道另一个 package 在你的之上构建了新的类

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.

相关问题 对于我的数据,我应该在 R 包 BNlearn 中使用交叉验证中的什么损失函数? - What loss function in cross-validation should I use with R package BNlearn for my data? 我应该如何格式化R mlogit软件包的数据? - How should I format my data for the R mlogit package? 用于 Tibbles、Data.Frames、矩阵等列表的 S3 通用 - S3 Generic for a List of Tibbles, Data.Frames, Matrices, Ect 如何对多个数据帧使用PAD函数(来自PADR()包)? - How can I use PAD function (from PADR() package) for multiple data frames? 将数据帧与OpenCPU的JavaScript库一起使用 - Use data frames with OpenCPU's JavaScript library 如何将数据框列表转换为可以与 x-13 季节性包一起使用的时间序列对象? - How do i turn a list of data frames into time series objects that i can use with the x-13 seasonal package? R我可以在包中使用.rds文件作为我的数据吗? - R Can I use .rds files for my data in a package? 当我在我的函数中使用另一个包的函数时我应该放什么 roxygen - What roxygen should I put when I use a function of another package in my function 如何在我的 R package 中将函数导出为 S3 方法? - How to export functions as S3 methods in my R package? 当我通过 ID 合并两个数据帧时,我没有获得其中一个数据帧的 ID - When i merge two data frames by ID's i do not get ID's for one of the data frames
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM