Search code examples
rsortinglevels

R: order the level of a factor vector based on the first number in the factor


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.


Solution

  • 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