reactable
reactable copied to clipboard
allow tidyselect for columGroups
As previously mentioned, wonderful package! thx again.
It would be very convenient if columnGroups would allow selecting columns with tidyselect (contains, starts_with etc). Using the example from the pkg site, something like:
reactable(
iris,
columns = list(
Sepal.Length = colDef(name = "Length"),
Sepal.Width = colDef(name = "Width"),
Petal.Length = colDef(name = "Length"),
Petal.Width = colDef(name = "Width")
),
columnGroups = list(
colGroup(name = "Sepal", columns = contains("Sepal"),
colGroup(name = "Petal", columns = contains("Petal")
)
)
Hi, that's an interesting idea, and it does look convenient. Could you use tidyselect to select columns outside of reactable? I'm totally unfamiliar with tidyselect and just skimmed the vignette at https://tidyselect.r-lib.org/articles/tidyselect.html. But it might be possible to write your own wrapper of reactable()
that supports tidyselect syntax for the column groups:
# Wrapper for reactable that supports tidyselect syntax in columnGroups
# Based on https://cran.r-project.org/web/packages/tidyselect/vignettes/tidyselect.html
# NOTE: not sure if this is totally correct but it seems to work
reactable <- function(data, columnGroups = NULL, ...) {
groups <- rlang::enquo(columnGroups)
groups <- rlang::get_expr(groups)[-1]
groups <- lapply(groups, function(group) {
pos <- tidyselect::eval_select(group$columns, data = data)
group$columns <- names(pos)
rlang::eval_tidy(group)
})
reactable::reactable(data, columnGroups = groups, ...)
}
Then you could use the drop-in reactable()
replacement like:
library(reactable)
library(tidyselect)
reactable(
iris,
columns = list(
Sepal.Length = colDef(name = "Length"),
Sepal.Width = colDef(name = "Width"),
Petal.Length = colDef(name = "Length"),
Petal.Width = colDef(name = "Width")
),
columnGroups = list(
colGroup(name = "Sepal", columns = contains("Sepal")),
colGroup(name = "Petal", columns = contains("Petal"))
)
)
While the syntax is convenient, I don't feel particularly strongly about building it into reactable. For this specific example, you could also use grep()
to select columns that contain or start with some pattern like:
reactable(
iris,
columns = list(
Sepal.Length = colDef(name = "Length"),
Sepal.Width = colDef(name = "Width"),
Petal.Length = colDef(name = "Length"),
Petal.Width = colDef(name = "Width")
),
columnGroups = list(
colGroup(name = "Sepal", columns = grep("Sepal", names(iris), value = TRUE)),
colGroup(name = "Petal", columns = grep("^Petal", names(iris), value = TRUE))
)
)
A simple workaround that has helped me is using str_subset()
on the column names e.g.
reactable(
iris,
columns = list(
Sepal.Length = colDef(name = "Length"),
Sepal.Width = colDef(name = "Width"),
Petal.Length = colDef(name = "Length"),
Petal.Width = colDef(name = "Width")
),
columnGroups = list(
colGroup(name = "Sepal", columns = str_subset(colnames(iris), "Sepal"),
colGroup(name = "Petal", columns = str_subset(colnames(iris), "Petal")
)
)