3

Context: I need to use factor order to make arrange diplays a table in a certain way. I.e I want to get a "Total" line at the end of each group.

Problem: using fct_relevel I acheive the expected output only within the first group.

Repex:

library(dplyr)
library(forcats)

total_masses <- starwars %>% 
  group_by(species) %>% 
  summarise(mass = sum(mass),
            name = "Total mass")

df <- bind_rows(starwars, total_masses) %>% 
  select(species, name, mass) %>% 
  group_by(species) %>% 
  mutate(name = fct_relevel(name, "Total mass", after = Inf)) %>% 
  arrange(mass, name, species) 
df
#> # A tibble: 125 x 3
#> # Groups:   species [38]
#>    species        name                   mass
#>    <chr>          <fct>                 <dbl>
#>  1 Aleena         Ratts Tyerell            15
#>  2 Aleena         Total mass               15
#>  3 Yoda's species Total mass               17 # I expect this line to be at the end of the Yoda's species group
#>  4 Yoda's species Yoda                     17
#>  5 Ewok           Total mass               20
#>  6 Ewok           Wicket Systri Warrick    20
#>  7 Droid          R2-D2                    32
#>  8 Droid          R5-D4                    32
#>  9 Dug            Total mass               40
#> 10 Dug            Sebulba                  40
#> # ... with 115 more rows

Created on 2021-05-31 by the reprex package (v2.0.0)

I expect each Total mass to be at the end of each species category:

   species        name                   mass
   <chr>          <fct>                 <dbl>
 1 Aleena         Ratts Tyerell            15
 2 Aleena         Total mass               15
 3 Yoda's species Yoda                     17
 4 Yoda's species Total mass               17
etc...

I feel like the solution is very obvious but I was not able to find the right keywords to solve it... Any tip is welcome!

Paul
  • 2,850
  • 1
  • 12
  • 37

1 Answers1

2

Then just do the fct_relevel without grouping, then group again and do anything you want within group.

library(dplyr)
library(forcats)

total_masses <- starwars %>% 
  group_by(species) %>% 
  summarise(mass = sum(mass),
    name = "Total mass")

# your codes
df <- bind_rows(starwars, total_masses) %>% 
  select(species, name, mass) %>% 
  group_by(species) %>% 
  mutate(name = fct_relevel(name, "Total mass", after = Inf)) %>% 
  arrange(mass, name, species) 
# Which result Total Mass is at 2nd so it will be above other levels
levels(df$name)
#>  [1] "Ratts Tyerell"         "Total mass"            "Dexter Jettster"      
#>  [4] "Ki-Adi-Mundi"          "Mas Amedda"            "Zam Wesell"           
#>  [7] "BB8"                   "C-3PO"                 "IG-88"                
...

Instead of that you can ungroup then fct_relevel, then group_by then arrange.

df <- bind_rows(starwars, total_masses) %>% 
  select(species, name, mass) %>% ungroup() %>%
  mutate(name = fct_relevel(name, "Total mass", after = Inf)) %>% 
  group_by(species) %>% 
  arrange(mass, name, species) 

# Output
df
#> # A tibble: 125 x 3
#> # Groups:   species [38]
#>    species        name                   mass
#>    <chr>          <fct>                 <dbl>
#>  1 Aleena         Ratts Tyerell            15
#>  2 Aleena         Total mass               15
#>  3 Yoda's species Yoda                     17
#>  4 Yoda's species Total mass               17
#>  5 Ewok           Wicket Systri Warrick    20
#>  6 Ewok           Total mass               20
#>  7 Droid          R2-D2                    32
#>  8 Droid          R5-D4                    32
#>  9 Dug            Sebulba                  40
#> 10 Dug            Total mass               40
#> # … with 115 more rows

# As you see now Total Mass is at the last item
levels(df$name)
#>  [1] "Ackbar"                "Adi Gallia"            "Anakin Skywalker"     
#>  [4] "Arvel Crynyd"          "Ayla Secura"           "Bail Prestor Organa"  
#>  [7] "Barriss Offee"         "BB8"                   "Ben Quadinaros"       
#> [10] "Beru Whitesun lars"    "Bib Fortuna"           "Biggs Darklighter"    
#> [13] "Boba Fett"             "Bossk"                 "C-3PO"                
#> [16] "Captain Phasma"        "Chewbacca"             "Cliegg Lars"          
#> [19] "Cordé"                 "Darth Maul"            "Darth Vader"          
#> [22] "Dexter Jettster"       "Dooku"                 "Dormé"                
#> [25] "Dud Bolt"              "Eeth Koth"             "Finis Valorum"        
#> [28] "Finn"                  "Gasgano"               "Greedo"               
#> [31] "Gregar Typho"          "Grievous"              "Han Solo"             
#> [34] "IG-88"                 "Jabba Desilijic Tiure" "Jango Fett"           
#> [37] "Jar Jar Binks"         "Jek Tono Porkins"      "Jocasta Nu"           
#> [40] "Ki-Adi-Mundi"          "Kit Fisto"             "Lama Su"              
#> [43] "Lando Calrissian"      "Leia Organa"           "Lobot"                
#> [46] "Luke Skywalker"        "Luminara Unduli"       "Mace Windu"           
#> [49] "Mas Amedda"            "Mon Mothma"            "Nien Nunb"            
#> [52] "Nute Gunray"           "Obi-Wan Kenobi"        "Owen Lars"            
#> [55] "Padmé Amidala"         "Palpatine"             "Plo Koon"             
#> [58] "Poe Dameron"           "Poggle the Lesser"     "Quarsh Panaka"        
#> [61] "Qui-Gon Jinn"          "R2-D2"                 "R4-P17"               
#> [64] "R5-D4"                 "Ratts Tyerell"         "Raymus Antilles"      
#> [67] "Rey"                   "Ric Olié"              "Roos Tarpals"         
#> [70] "Rugor Nass"            "Saesee Tiin"           "San Hill"             
#> [73] "Sebulba"               "Shaak Ti"              "Shmi Skywalker"       
#> [76] "Sly Moore"             "Tarfful"               "Taun We"              
#> [79] "Tion Medon"            "Wat Tambor"            "Watto"                
#> [82] "Wedge Antilles"        "Wicket Systri Warrick" "Wilhuff Tarkin"       
#> [85] "Yarael Poof"           "Yoda"                  "Zam Wesell"           
#> [88] "Total mass"

Created on 2021-05-31 by the reprex package (v2.0.0)

AndrewGB
  • 16,126
  • 5
  • 18
  • 49
Sinh Nguyen
  • 4,277
  • 3
  • 18
  • 26