【发布时间】:2017-06-17 11:41:18
【问题描述】:
我有一个包含自定义 summary()、print() 方法的包,用于具有特定类的对象。这个包还使用了出色的 dplyr 包进行数据操作 - 我希望我的用户编写脚本同时使用我的包和 dplyr。
其他人 here 和 here 注意到的一个障碍是 dplyr 动词不保留自定义类 - 这意味着 ungroup 命令可以剥离我的 data.frames 他们的自定义类,因此搞砸summary等的方法调度
Hadley 说“正确执行此操作取决于您 - 您需要为每个 dplyr 方法为您的类定义一个方法,以正确恢复所有类和属性”,我正在尝试采用 advice - 但我无法弄清楚如何正确包装 dplyr 动词。
这是一个简单的玩具示例。假设我已经定义了一个 cars 类,并且我有一个自定义的 summary 用于它。
这行得通
library(tidyverse)
class(mtcars) <- c('cars', class(mtcars))
summary.cars <- function(x, ...) {
#gather some summary stats
df_dim <- dim(x)
quantile_sum <- map(mtcars, quantile)
cat("A cars object with:\n")
cat(df_dim[[1]], 'rows and ', df_dim[[2]], 'columns.\n')
print(quantile_sum)
}
summary(mtcars)
问题来了
small_cars <- mtcars %>% filter(cyl < 6)
summary(small_cars)
class(small_cars)
summary 调用 small_cars 只是给了我通用摘要,而不是我的自定义方法,因为 small_cars 在 dplyr 过滤后不再保留 cars 类。
我尝试了什么
首先,我尝试围绕filter (filter.cars) 编写自定义方法。这不起作用,因为 filter 实际上是 filter_ 的包装器,它允许进行非标准评估。
所以我为cars对象编写了一个自定义的filter_方法,试图实现@jwdink的advice
filter_.cars <- function(df, ...) {
old_classes <- class(df)
out <- dplyr::filter_(df, ...)
new_classes <- class(out)
class(out) <- c(new_classes, old_classes) %>% unique()
out
}
这不起作用 - 我得到一个无限递归错误:
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
Error during wrapup: evaluation nested too deeply: infinite recursion / options(expressions=)?
我想要做的就是获取传入 df 上的类,交给 dplyr,然后返回具有与 dplyr 调用之前相同的类名的对象。 如何更改我的 filter_ 包装器以完成此操作?谢谢!
【问题讨论】:
标签: r dplyr r-package tidyverse r-s3