reactable icon indicating copy to clipboard operation
reactable copied to clipboard

Sort factors by levels

Open ccamara opened this issue 4 years ago • 2 comments

Reactable is configured to let columns to be sortable, which is great. Unfortunately, the sorting doesn't seem to work with factor levels.

While by default factor levels are sorted alphabetically, this is not always the case.

Take the code below as an example: I would love to see the column species sorted according to the levels' order (Human, and then the rest of levels, alphabetically), but instead, they are sorted alphabetically.

library(tidyverse)

starwars2<- starwars %>% 
  mutate(species = fct_relevel(as.factor(species), "Human"))

reactable(
  starwars2,
  defaultSortOrder = "desc",
  columns = list(
    species = colDef(defaultSortOrder = "asc")
  )
)

This is the output:

> levels(starwars2$species)
 [1] "Human"          "Aleena"         "Besalisk"       "Cerean"         "Chagrian"       "Clawdite"      
 [7] "Droid"          "Dug"            "Ewok"           "Geonosian"      "Gungan"         "Hutt"          
[13] "Iktotchi"       "Kaleesh"        "Kaminoan"       "Kel Dor"        "Mirialan"       "Mon Calamari"  
[19] "Muun"           "Nautolan"       "Neimodian"      "Pau'an"         "Quermian"       "Rodian"        
[25] "Skakoan"        "Sullustan"      "Tholothian"     "Togruta"        "Toong"          "Toydarian"     
[31] "Trandoshan"     "Twi'lek"        "Vulptereen"     "Wookiee"        "Xexto"          "Yoda's species"
[37] "Zabrak" 

reactable

ccamara avatar Oct 05 '21 09:10 ccamara

Curious if anything ever came of this?

mrworthington avatar Sep 10 '24 19:09 mrworthington

Unfortunately it looks like this functionality isn't supported, but it was something I needed to work around as well. I was able to use the cell argument in the colDef() function to get the sorting I needed by coercing the factor to numeric and then displaying the label from another column in the cell instead of the numeric. Some other housekeeping is also needed to have the same column order and column names.

With data from @ccamara

library(reactable)
library(tidyverse)

starwars2 <- starwars %>%
  mutate(
    species = fct_relevel(as.factor(species), "Human"),
    species_sort = as.numeric(species),
    species_display = as.character(species)
  ) %>%
  relocate(
    species_sort, .after = species
  )

reactable(
  starwars2,
  defaultSortOrder = "desc",
  columns = list(
    species_sort = colDef(
      defaultSortOrder = "asc",
      name = "species",
      cell = function(value, index) {
        starwars2$species_display[index]
      },
      sortNALast = T
    ),
    species_display = colDef(show = F),
    species = colDef(show = F)
  )
)

ntentes avatar Feb 28 '25 00:02 ntentes