Clean way to reorder tidyr spread after nest and purrr map

411 views Asked by At

Consider the following:

library(tidyverse)
library(broom)

tidy.quants <- mtcars %>%
  nest(-cyl) %>%
  mutate(quantiles = map(data, ~ quantile(.$mpg))) %>%
  unnest(map(quantiles, tidy))

tidy.quants
#> # A tibble: 15 x 3
#>      cyl names     x
#>    <dbl> <chr> <dbl>
#>  1     6    0% 17.80
#>  2     6   25% 18.65
#>  3     6   50% 19.70
#>  4     6   75% 21.00
#>  5     6  100% 21.40
#>  6     4    0% 21.40
#>  7     4   25% 22.80
#>  8     4   50% 26.00
#>  9     4   75% 30.40
#> 10     4  100% 33.90
#> 11     8    0% 10.40
#> 12     8   25% 14.40
#> 13     8   50% 15.20
#> 14     8   75% 16.25
#> 15     8  100% 19.20

Which is great and tidy, however, when attempting to spread (or pass to a plot), the names column returns in a (somewhat) unexpected order:

tidy.quants %>% spread(names, x)
#> # A tibble: 3 x 6
#>     cyl  `0%` `100%` `25%` `50%` `75%`
#> * <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl>
#> 1     4  21.4   33.9 22.80  26.0 30.40
#> 2     6  17.8   21.4 18.65  19.7 21.00
#> 3     8  10.4   19.2 14.40  15.2 16.25

ggplot(tidy.quants, aes(x = names, y = x, color = factor(cyl))) +
  geom_point()

enter image description here

Is there a clean/idiomatic way to have have the names return back in their expected order? That is, 0%, 25%, 50%, 75%, 100% instead of 0%, 100%, 25%, 50%, 75%?

2

There are 2 answers

0
moodymudskipper On BEST ANSWER

This works because names are already sorted by quantiles:

tidy.quants <- mtcars %>%
  nest(-cyl) %>%
  mutate(quantiles = map(data, ~ quantile(.$mpg))) %>%
  unnest(map(quantiles, tidy)) %>%
  mutate(names=factor(names,unique(names)))

tidy.quants %>% spread(names, x)

result

# A tibble: 3 x 6
    cyl  `0%` `25%` `50%` `75%` `100%`
* <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
1     4  21.4 22.80  26.0 30.40   33.9
2     6  17.8 18.65  19.7 21.00   21.4
3     8  10.4 14.40  15.2 16.25   19.2
0
Psidom On

You can try gtools::mixedsort, which can sort strings with embedded numbers; After getting the sorted labels with mixedsort(unique(names)), similar to color, you can make names(x axis variable) a factor with the sorted values as levels, ggplot should then be able to display the x axis label in the correct order:

library(gtools)
ggplot(tidy.quants, aes(x = factor(names, levels = mixedsort(unique(names))), y = x, color = factor(cyl))) +
    geom_point() + xlab('names')

enter image description here


Similar idea for spread:

tidy.quants %>% 
    mutate(names = factor(names, mixedsort(unique(names)))) %>% 
    spread(names, x)

# A tibble: 3 x 6
#    cyl  `0%` `25%` `50%` `75%` `100%`
#* <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
#1     4  21.4 22.80  26.0 30.40   33.9
#2     6  17.8 18.65  19.7 21.00   21.4
#3     8  10.4 14.40  15.2 16.25   19.2