reactable icon indicating copy to clipboard operation
reactable copied to clipboard

option to provide column order

Open aronatkins opened this issue 3 years ago • 2 comments

It would be groovy to have a way of specify the display column order without rewriting the incoming data frame.

In my situation, the incoming data frame is not created by me; it is produced by some other R package using whatever column ordering it believes to be useful.

I am already enumerating many columns in the columns argument to reactable to supply names, formats, etc. Maybe the columns ordering should be the display order?

My current workaround is to recreate the data frame with my desired column order before passing to reactable. Because of #171, I am also trimming undesirable columns at the same time.

library(magrittr)
library(dplyr)

# imagine that df came from another package...
df <- data.frame(
    unwanted = c(0,0,0,0),
    second = c(2,4,6,8),
    first = c(1,2,3,4)
)

df_table <- df %>% dplyr::select(first, second)

reactable::reactable(
  df_table,
  columns = list(
    first = reactable::colDef(name = "First"),
    second = reactable::colDef(name = "Second")
  )
)

aronatkins avatar Jun 21 '21 19:06 aronatkins

Thanks for the feature request. I've thought about adding this for a while, but have always been on the fence about it. There were a couple issues/questions I had, and maybe you have some thoughts on them:

  1. If reactable uses the columns ordering, what happens if you don't specify all columns? Are the unspecified columns moved to the end, dropped, or something else? I don't know what would make sense unless you explicitly provide every column in the list. And if you have to specify all columns, doing it in the column definitions would be tedious in many cases, so it might be better off as a separate argument like columnOrder = c("col1", "col2").

  2. It's already fairly simple to reorder columns using something like df[, c("col1", "col2")] or dplyr's select(). This is what I always ended up doing in practice, so it felt redundant to add a column order argument that does the same thing. dplyr::select() is also way more powerful at reordering columns, as you can use tidyselect to do things like dplyr::select(mtcars, disp, everything()).

    To be more concise, I sometimes reorder columns like:

    reactable::reactable(
      mtcars[, c("mpg", "hp", "cyl")]
    )
    
    reactable::reactable(
      mtcars %>% dplyr::select(mpg, hp, cyl)
    )
    

    Which isn't a whole lot different from a separate column order argument:

    reactable::reactable(
      mtcars,
      columnOrder = c("mpg", "hp", "cyl")
    )
    

    On the other hand, this isn't as practical if you're creating a table with someone else's crosstalk::SharedData object (which has been brought up before), so the separate column order argument would be nice in that case. But that can still be worked around, and it's still kind of a niche use case.

glin avatar Jul 11 '21 23:07 glin

I filed this issue because I found that I was making mistakes when altering the columns in the display. I would add a value to reactable::reactable(columns=...) but forget to add it to my dplyr::select list, or vice-versa. This redundancy led to oversight which led to additional iteration during development.

My columns values included all data columns because I was renaming columns in an API-fetched data-frame (snake case names like active_time) to display-friendly names (like "Last Active").

I'm not sure how to wrangle this issue given the current API.

If a dataframe could be augmented with metadata outside the presentation, it might be an option, but that feels like a different composition metaphor (pseudocode):

# ordered subset of, configured columns
df %>% reactable::select(
  mpg = reactable::colDef(name = "Miles per Gallon"),
  ...  
) %>% reactable::reactable()

# augment incoming dataframe with optional presentation metadata
df %>% reactable::mutate(
  mpg = reactable::colDef(name = "Miles per Gallon"),
  ...
) %>% reactable::reactable()

The underlying idea is: Convert the raw data frame into a "presentation" reactable data frame and operate on that before passing the fully configured data to reactable.

Feel free to close "as designed". I mostly wanted to communicate my difficulties in case it helps inform some future evolution.

aronatkins avatar Jul 12 '21 13:07 aronatkins