Reputation: 634
I'd like to build a structure which essentially is a data.frame/tibble but it has an extra custom class. I'd use this class for quick checks in other part of code to ensure that I can perform certain operations on the data. But dplyr throws an error when I try to filter the data. Please, look at the code below:
my_data_frame <- function(x) {
stopifnot(is.data.frame(x))
class(x) <- append(class(x), "my_data_frame")
return(x)
}
# create an instance of the class
my_iris <- my_data_frame(iris)
class(my_iris) # ---> "data.frame" "my_data_frame"
# try filtering
dplyr::filter(my_iris, Sepal.Length > 0.56)
The last command gives the following error
Error in `stop_vctrs()`:
! Input must be a vector, not a <data.frame/my_data_frame> object.
I found dplyr_row_slice
function and read the help here https://dplyr.tidyverse.org/reference/dplyr_extending.html. I tried to extend the function like this:
dplyr_row_slice.my_data_frame <- function(data, i, ...) {
message("custom handler invoked")
# filtering code
# ???
}
but it doesn't work. Maybe I miss something? How should I properly implement filtering so it works like in dplyr package?
Upvotes: 0
Views: 140
Reputation: 634
I found a solution. Inspired by @MrFlick's comment I rearranged the class assignment, i.e. my custom class is assigned as the first one in the list of classes:
class(x) <- append("my_data_frame", class(x))
Next, I implemented filtering the following way:
dplyr_row_slice.my_data_frame <- function(data, i, ...) {
data_tbl <- as.data.frame(data)
dplyr::dplyr_row_slice(data, i, ...)
}
i.e. first coercing the data to pure data.frame
class and then using native dplyr's implementation of dplyr_row_slice
method. The latter uses dplyr_reconstruct
under the hood, as you can see here https://github.com/tidyverse/dplyr/blob/main/R/generics.R. This brings my custom class back after the filtering is done.
Upvotes: 1