I want to order the level of a factor vector based on the first number in the factor.
Below is the example:
FC <- factor(c("R: 12.22 P: 170.0", "R: 12.98 P: 189.1", "R: 2.55 P: 286", "R: 12.22 P: 170.0", "R: 12.98 P: 189.1", "R: 2.55 P: 286"))
## the original level oder
FC
[1] R: 12.22 P: 170.0 R: 12.98 P: 189.1 R: 2.55 P: 286 R: 12.22 P: 170.0 R: 12.98 P: 189.1 R: 2.55 P: 286
Levels: R: 12.22 P: 170.0 R: 12.98 P: 189.1 R: 2.55 P: 286
I want the level to be ordered according to the first number in the factor in the example, i.e., in the order of 2.55
, 12.22
and 12.98
The result will be like below:
## ordered level
FC
Levels: R: 2.55 P: 286 R: 12.22 P: 170.0 R: 12.98 P: 189.1
What I am thinking to extract the first number in the factor vector, and then order the factor.
fistNum <- read.table(text = levels(FC))[[2]]
fistNum
[1] 12.22 12.98 2.55
I then don't know how to continue. Thanks for your help.
CodePudding user response:
Something like this ?
levels(FC) <- FC[order(readr::parse_number(as.character(levels(FC))))]
levels(FC)
#[1] "R: 2.55 P: 286" "R: 12.22 P: 170.0" "R: 12.98 P: 189.1"
readr::parse_number
would extract the first number from the vector FC
, we order
those numbers and assign the levels
CodePudding user response:
In base
FC <- factor(c("R: 12.22 P: 170.0", "R: 12.98 P: 189.1", "R: 2.55 P: 286", "R: 12.22 P: 170.0", "R: 12.98 P: 189.1", "R: 2.55 P: 286"))
# Coherce to character for gsub
cc <- paste(FC)
cc
#> [1] "R: 12.22 P: 170.0" "R: 12.98 P: 189.1" "R: 2.55 P: 286"
#> [4] "R: 12.22 P: 170.0" "R: 12.98 P: 189.1" "R: 2.55 P: 286"
# Get first value in each string
fv <- gsub(pattern = ".*\\s([0-9.]*)\\s.*", replacement = "\\1", x = cc)
fv
#> [1] "12.22" "12.98" "2.55" "12.22" "12.98" "2.55"
df <- data.frame(cbind(cc, fv))
df
#> cc fv
#> 1 R: 12.22 P: 170.0 12.22
#> 2 R: 12.98 P: 189.1 12.98
#> 3 R: 2.55 P: 286 2.55
#> 4 R: 12.22 P: 170.0 12.22
#> 5 R: 12.98 P: 189.1 12.98
#> 6 R: 2.55 P: 286 2.55
FC <- factor(FC, levels = unique(df[order(as.numeric(df$fv)),"cc"]))
FC
#> [1] R: 12.22 P: 170.0 R: 12.98 P: 189.1 R: 2.55 P: 286 R: 12.22 P: 170.0
#> [5] R: 12.98 P: 189.1 R: 2.55 P: 286
#> Levels: R: 2.55 P: 286 R: 12.22 P: 170.0 R: 12.98 P: 189.1
CodePudding user response:
Thanks @Ronak Shah. Following your answer, I have added another answer with base R.
levels(FC) <- levels(FC)[order(read.table(text = levels(FC), fill = TRUE)[[2]])]
CodePudding user response:
We could use fct_relevel
library(forcats)
FC2 <- fct_relevel(FC, gtools::mixedsort(levels(FC)))
levels(FC2)
[1] "R: 2.55 P: 286" "R: 12.22 P: 170.0" "R: 12.98 P: 189.1"