R语言 使用S7 Package S3类

6rvt4ljy  于 2023-10-13  发布在  其他
关注(0)|答案(1)|浏览(135)

我正在尝试使用R(https://github.com/RConsortium/S7)引入的新S7 OOP。我想使用S7来 Package 一元运算符|的S3方法。
我有一个类"ggsurvfit"的对象,我想定义三个新方法:

`|`(ggsurvfit, ggsurvfit)
`|`(ggsurvfit, ggplot)
`|`(ggplot, ggsurvfit)

几周前,我有幸与Hadley威克姆(他是R Consortium开发S7团队的一员)在同一个房间里,他友好地为我提供了下面的代码,用S7 Package S3方法。(我添加了返回的文本字符串FYI)

method(`|`, list(new_S3_class("ggsurvfit"), new_S3_class("ggsurvfit"))) <- function(e1, e2) { 
  "This is ggsurvfit|ggsurvfit"
}
method(`|`, list(new_S3_class("ggsurvfit"), new_S3_class("ggplot"))) <- function(e1, e2) { 
  "This is ggsurvfit|ggplot"
}
method(`|`, list(new_S3_class("ggplot"), new_S3_class("ggsurvfit"))) <- function(e1, e2) { 
  "This is ggplot|ggsurvfit"
}

我遇到的问题是,我无法启动/触发这些方法。在下面的例子中,我希望/期望操作返回字符串"This is ggsurvfit|ggplot"。我错过了什么?谢谢您的支持!

library(ggsurvfit)
#> Loading required package: ggplot2

S7::method(`|`, list(S7::new_S3_class("ggsurvfit"), S7::new_S3_class("ggplot"))) <- function(e1, e2) { 
  "This is ggsurvfit|ggplot"
}

plot1 <- 
  survfit2(Surv(time, status) ~ sex, data = df_lung) |> 
  ggsurvfit() +
  add_risktable()
class(plot1)
#> [1] "ggsurvfit" "gg"        "ggplot"

plot2 <- 
  ggplot(mtcars, aes(mpg, cyl)) +
  geom_point()
class(plot2)
#> [1] "gg"     "ggplot"

ret <- plot1 | plot2
#> Error in plot1 | plot2: operations are possible only for numeric, logical or complex types

创建于2023-10-10使用reprex v2.0.2

eyh26e7m

eyh26e7m1#

我认为问题在于|不是S7方法,"ggsurvfit"也不是S7类。关于method<-的文档说,

  • 这不是一个通用的方法注册函数:通用和签名中至少有一个需要来自S7*。

将现有的S3类 Package 在new_S3_class中并不会使其成为S7类-它只是声明您想要使用的类是S3。由于您可能不想让|成为S7的泛型,因此最好的选择可能是将ggsurvfit Package 在S7类中。这似乎是一个诀窍:

library(S7)
library(ggsurvfit)
#> Loading required package: ggplot2

ggsurvfit_S7 <- new_class("ggsurvfit_S7",
                   properties = list(
                     obj = new_S3_class("ggsurvfit")
                   )
)

method(`|`, list(ggsurvfit_S7, new_S3_class("ggplot"))) <- function(e1, e2) { 
  "This is ggsurvfit|ggplot"
}

method(`|`, list(new_S3_class("ggplot"), ggsurvfit_S7)) <- function(e1, e2) { 
  "This is ggplot|ggsurvfit"
}

method(`|`, list(ggsurvfit_S7, ggsurvfit_S7)) <- function(e1, e2) { 
  "This is ggsurvfit|ggsurvfit"
}

当然,您需要在这个示例的 Package 器中创建ggsurvfit。在生产环境中,您可能会将ggsurvfit重写为 * 成为 * 一个S7类,但这给了您这样的想法:

plot1 <- ggsurvfit_S7(
  obj = survfit2(Surv(time, status) ~ sex, data = df_lung) |> 
        ggsurvfit() +
        add_risktable()
  )

plot2 <- ggplot(mtcars, aes(mpg, cyl)) + geom_point()

但正确的行为是观察:

plot1 | plot2
#> [1] "This is ggsurvfit|ggplot"

plot2 | plot1
#> [1] "This is ggplot|ggsurvfit"

plot1 | plot1
#> [1] "This is ggsurvfit|ggsurvfit"

当然,您需要为 Package 器定义一个print方法,但这在S7中似乎非常简单

method(print, ggsurvfit_S7) <- function(x, ...) print(x@obj, ...)

plot1

创建于2023-10-10使用reprex v2.0.2

相关问题