Reputation: 1353
Let say I have below vector
vec = c('1d', '3m', '5d', '10y', '1m')
here, m
means months, d
means day, and y
means year. I want to sort the vector in ascending order of day, month, and year. So ideally the sorted vector will be -
c('1d', '5d', '1m', '3m', '10y')
Is there any way to achieve this using R's base libraries (I am restricted to download contributed packages).
Thanks for your time.
Upvotes: 0
Views: 56
Reputation: 886938
We can use str_replace
library(stringr)
vec[order(sapply(str_replace_all(vec, setNames( c('*1', '*30', '*365'),
c('d', 'm', 'y'))), function(x) eval(parse(text = x))))]
#[1] "1d" "5d" "1m" "3m" "10y"
Or an option with separate
library(dplyr)
library(tidyr)
tibble(vec) %>%
separate(vec, into = c('v1', 'v2'), sep='(?<=\\d)(?=\\D)',
convert = TRUE, remove = FALSE) %>%
arrange(v2, v1) %>%
pull(vec)
#[1] "1d" "5d" "1m" "3m" "10y"
Or can also use a matching with a named vector to order
vec[order(readr::parse_number(vec) *
(setNames(c(1, 7, 30, 365), c('d', 'w', 'm', 'y'))[str_remove(vec, '\\d+')]))]
#[1] "1d" "5d" "1m" "3m" "10y"
vec <- c('1d', '3m', '5d', '10y', '1m')
Upvotes: 0
Reputation: 101064
Since the lexical order of d
, m
and y
is d < m < y
already, you can try the code below
> vec[order(gsub("\\d+", "", vec), as.numeric(gsub("\\D+", "", vec)))]
[1] "1d" "5d" "1m" "3m" "10y"
Upvotes: 0
Reputation: 388817
Extract d
, m
and y
value separately and extract the number separately. Create a vector of correct_order
that you want, use match
to get corresponding number and use it in order
.
vec = c('1d', '3m', '5d', '10y', '1m')
correct_order <- c('d', 'm', 'y')
vec[order(match(gsub('\\d', '', vec), correct_order),
as.numeric(gsub('\\D', '', vec)))]
#[1] "1d" "5d" "1m" "3m" "10y"
Upvotes: 2