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"
