dplyr::group_by丢失自定义tibble子类类,S3打印方法无法调度怎么办?
解决dplyr::group_by丢弃自定义tibble子类的问题
你遇到的问题是dplyr分组操作后默认会将对象类替换为grouped_df,覆盖了自定义的my_tbl类,导致自定义打印方法失效——这确实是dplyr的设计行为,而非bug。下面是两种规范的处理方式,优先推荐第一种:
方法一:用dplyr_reconstruct保留自定义类
dplyr提供了dplyr_reconstruct泛型函数,专门用于在数据操作后重建自定义子类的类结构,这是官方推荐的处理方式,能覆盖所有dplyr操作(不只是group_by)。
实现代码如下:
library(tibble) library(dplyr) # 定义自定义tibble子类 my_tbl <- function(x) { new_tibble(x, class = "my_tbl") } # 自定义打印表头的tbl_sum方法 tbl_sum.my_tbl <- function(x) { c("My Fancy Header" = "Whooaaaa!") } # 实现dplyr_reconstruct,保留自定义类 dplyr_reconstruct.my_tbl <- function(data, template) { # 先执行默认的重建逻辑,得到grouped_df对象 reconstructed <- NextMethod() # 将自定义类添加到类向量的最前面 class(reconstructed) <- c("my_tbl", class(reconstructed)) reconstructed } # 测试原始对象 (mt <- my_tbl(mtcars %>% slice(1L))) # 分组后会保留my_tbl类,打印自定义表头 mt %>% group_by(am) # 查看类:同时包含my_tbl和grouped_df class(mt %>% group_by(am)) # [1] "my_tbl" "grouped_df" "tbl_df" "tbl" "data.frame"
方法二:为grouped_df实现tbl_sum方法
如果不想修改分组后的类结构,也可以直接为grouped_df类型实现tbl_sum方法,判断对象是否属于自定义子类后调用自定义打印逻辑:
tbl_sum.grouped_df <- function(x) { if (inherits(x, "my_tbl")) { # 自定义表头+分组信息 c("My Fancy Header" = "Whooaaaa!", "Groups" = toString(group_vars(x))) } else { # 调用默认的grouped_df打印逻辑 NextMethod() } }
注意:不推荐直接重载group_by
直接重载dplyr::group_by只能覆盖单个操作,而dplyr还有大量其他数据操作(如group_by_at、summarise等)都会修改类结构,使用dplyr_reconstruct能统一处理所有场景,是更健壮的方案。
内容的提问来源于stack exchange,提问作者thothal
相关产品推荐
相关产品推荐

