Combination of `arrange()` and `group_map()` does not produce expected result?

library(tidyverse)

d <- tibble(
  a = letters[1:5],
  b = 1:5,
  x = 11:15
)
d
#> # A tibble: 5 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 a         1    11
#> 2 b         2    12
#> 3 c         3    13
#> 4 d         4    14
#> 5 e         5    15



d %>% 
  arrange(desc(b)) %>% 
  group_by(a, b) %>% 
  group_map( ~ ., keep = TRUE )
#> [[1]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 a         1    11
#> 
#> [[2]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 b         2    12
#> 
#> [[3]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 c         3    13
#> 
#> [[4]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 d         4    14
#> 
#> [[5]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 e         5    15




# but I'd like the list to be ordered by `desc(b)` like this:

#> [[1]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 e         5    15


#> [[2]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 d         4    14



#> [[3]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 c         3    13


#> [[4]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 b         2    12


#> [[5]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 a         1    11

Created on 2020-01-06 by the reprex package (v0.3.0)

It seems like group_by implicitly orders the grouping variables. If you try

d_rev <- d %>% 
	arrange(desc(b))

group_data(d_rev %>% 
		      group_by(a, b))

the result is

# A tibble: 5 x 3
  a         b .rows    
  <chr> <int> <list>   
1 a         1 <int [1]>
2 b         2 <int [1]>
3 c         3 <int [1]>
4 d         4 <int [1]>
5 e         5 <int [1]>

so - in this case it orders first by a and then by b even though we don't see that explicitly because they are ordered in the same way. So, you can try to "trick" group_by like this:

d %>% 
	arrange(desc(b)) %>% 
	group_by(a, mb = -b) %>% 
	group_map( ~ ., keep = TRUE)

but that will still not work since it will first order by a. So finally, you can do this

d %>% 
	arrange(desc(b)) %>% 
	group_by(ma = rev(a), mb = -b) %>% 
	group_map( ~ ., keep = TRUE)

which will order the list as you wish (and then you can remove the unnecessary ma and mb). But in a more general case where a and b can have a more complicated relationship this will not generalize.

Have a look at this potential solution and see if it works for you

library(tidyverse)

d <- tibble(
    a = letters[1:5],
    b = 1:5,
    x = 11:15
)

d
#> # A tibble: 5 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 a         1    11
#> 2 b         2    12
#> 3 c         3    13
#> 4 d         4    14
#> 5 e         5    15

l <- d %>% 
    arrange(desc(b)) %>% 
    group_by(a, b) %>% 
    group_map( ~ ., keep = TRUE)

d_rev <- d %>% 
    arrange(desc(b))

group_rows <- group_rows(d %>% 
                                                    arrange(desc(b)) %>% 
                                                    group_by(a, b)) %>% 
    unlist()

l <- l[group_rows]
l
#> [[1]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 e         5    15
#> 
#> [[2]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 d         4    14
#> 
#> [[3]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 c         3    13
#> 
#> [[4]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 b         2    12
#> 
#> [[5]]
#> # A tibble: 1 x 3
#>   a         b     x
#>   <chr> <int> <int>
#> 1 a         1    11

Created on 2020-01-06 by the reprex package (v0.3.0)

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.