I have a data frame with numerical values as column names. These columns have resulted from a pivot_wider()
operation and contain both positive and negative values. I would like to get the columns in ascending numerical order without having to hard code the variable names (since I need to repeat this operation on multiple data frames).
A reprex is given below.
library(tidyverse)
# This is the input data frame. Notice that the columns `-1` and `3` are out of place.
df <- tribble(~col1, ~col2, ~`-3`, ~`-2`, ~`0`, ~`1`, ~`2`, ~`-1`, ~`4`, ~`3`,
"A", "B", NA, 1, 15, 98, 183, 445, 2, 487,
"C", "D", NA, NA, 6, 26, 146, 571, NA, 82)
print(df)
#> # A tibble: 2 x 10
#> col1 col2 `-3` `-2` `0` `1` `2` `-1` `4` `3`
#> <chr> <chr> <lgl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A B NA 1 15 98 183 445 2 487
#> 2 C D NA NA 6 26 146 571 NA 82
# This is the expected result.
output <- tribble(~col1, ~col2, ~`-3`, ~`-2`, ~`-1`, ~`0`, ~`1`, ~`2`, ~`3`, ~`4`,
"A", "B", NA, 1, 445, 15, 98, 183, 487, 2,
"C", "D", NA, NA, 571, 6, 26, 146, 82, NA)
print(output)
#> # A tibble: 2 x 10
#> col1 col2 `-3` `-2` `-1` `0` `1` `2` `3` `4`
#> <chr> <chr> <lgl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A B NA 1 445 15 98 183 487 2
#> 2 C D NA NA 571 6 26 146 82 NA
Here's what I've tried so far.
# str_sort() doesn't give the desired result.
df %>%
select(col1, col2, str_sort(colnames(.), numeric = TRUE))
#> # A tibble: 2 x 10
#> col1 col2 `-1` `-2` `-3` `0` `1` `2` `3` `4`
#> <chr> <chr> <dbl> <dbl> <lgl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A B 445 1 NA 15 98 183 487 2
#> 2 C D 571 NA NA 6 26 146 82 NA
# Setting the decreasing parameter is no good either.
df %>%
select(col1, col2, str_sort(colnames(.), decreasing = TRUE, numeric = TRUE))
#> # A tibble: 2 x 10
#> col1 col2 `4` `3` `2` `1` `0` `-3` `-2` `-1`
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <lgl> <dbl> <dbl>
#> 1 A B 2 487 183 98 15 NA 1 445
#> 2 C D NA 82 146 26 6 NA NA 571
I attempted to break the problem down into smaller pieces by first selecting only the negative values and then only the positive values but the columns still need to be sorted.
df %>%
select_at(vars(contains("col"), contains("-"), !contains("-")))
#> # A tibble: 2 x 10
#> col1 col2 `-3` `-2` `-1` `0` `1` `2` `4` `3`
#> <chr> <chr> <lgl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A B NA 1 445 15 98 183 2 487
#> 2 C D NA NA 571 6 26 146 NA 82
Now if I could just apply str_sort()
to each set of selections, that would do the trick but I'm not able to figure out how. Can someone please help?
Created on 2020-03-03 by the reprex package (v0.3.0)