Reorder Levels of a Factor Without Changing Order of Values

Reorder levels of a factor without changing order of values

Use the levels argument of factor:

df <- data.frame(f = 1:4, g = letters[1:4])
df
# f g
# 1 1 a
# 2 2 b
# 3 3 c
# 4 4 d

levels(df$g)
# [1] "a" "b" "c" "d"

df$g <- factor(df$g, levels = letters[4:1])
# levels(df$g)
# [1] "d" "c" "b" "a"

df
# f g
# 1 1 a
# 2 2 b
# 3 3 c
# 4 4 d

How to reorder the levels of a factor in increasing or decreasing order?

you need to summarise the categories first:

 library(tidyverse)
my_file <- read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2018-10-16/recent-grads.csv")

my_file %>%

# summarise categories
group_by(Major_category) %>%
summarise(Unemployed = sum(Unemployed, na.rm = TRUE)) %>%

#now use your code
mutate(Major_category = fct_reorder(Major_category, Unemployed)) %>%
ggplot(aes(x = Major_category,
y = Unemployed,
fill = Major_category)) +
geom_bar(stat = "identity") +
theme_minimal() +
labs(title = "Unemployed Students in Various Majors", x ="Major") +
theme(legend.position = "none",
plot.title = element_text(hjust = 0.5)) +
coord_flip()

output is:
Sample Image

set factor levels in specific order

Use the levels = argument.

tbl <- tibble(states = c("FL", "NY", "CA", "IN")) %>%
mutate(states_fct = factor(states, levels = c("CA", "IN", "FL", "NY"))

Reorder factor levels by pattern

You can create your desired factor levels programmatically.

lvls <- do.call(paste, c(tidyr::expand_grid(
c('Female', 'Male'), c('18_34', '35_49'), c('HS', 'CG')), sep = '-'))
lvls
#[1] "Female-18_34-HS" "Female-18_34-CG" "Female-35_49-HS" "Female-35_49-CG"
#[5] "Male-18_34-HS" "Male-18_34-CG" "Male-35_49-HS" "Male-35_49-CG"

You can use this lvls as levels in the factor call.

How can I swap the levels?

Use the factor() function:

a <- c("No", "Yes", "No", "Yes", "Yes")
af <- factor(a, levels = c("Yes","No"))

Reorder factor levels within group

To reorder the factor levels you can use forcats (part of the tidyverse), and do something like this...

library(forcats)
df2 <- df %>% mutate(a_factor = fct_reorder(a_factor,
value*(-1 + 2 * (group=="group1"))))

levels(df2$a_factor)
[1] "f" "e" "d" "a" "b" "c"

This does not rearrange the dataframe itself...

df2
a_factor group value
1 a group1 1
2 b group1 2
3 c group1 3
4 d group2 4
5 e group2 5
6 f group2 6

Reorder factor levels based on another factor

Assuming I understand what you are after, you can try ordering your data.frame and then passing the fac1 as the (order of) levels.

data$fac1 <- factor(data$fac1, levels = data[order(data$fac2), "fac1"])
levels(data$fac1)

> data
fac1 fac2
1 jj45 md
2 yy85 md
3 ee78 md
4 ww77 md
5 dd85 av
6 jj63 av
7 ee12 av
8 ee01 av
9 yy25 zr
10 tt23 zr
11 tt78 zr
12 qq74 zr
13 qe89 kj
14 gs85 kj
15 vd51 kj
16 vd41 kj
> levels(data$fac1)
[1] "jj45" "yy85" "ee78" "ww77" "dd85" "jj63" "ee12" "ee01" "yy25"
[10] "tt23" "tt78" "qq74" "qe89" "gs85" "vd51" "vd41"

Re-ordering factor levels in data frame

Assuming your dataframe is mydf:

mydf$task <- factor(mydf$task, levels = c("up", "down", "left", "right", "front", "back"))

Sorting the values inside row in a data frame, by the order of its factor levels?

In your code, the issue is happening at this line.

arcana_table <- as.data.frame(matrix(shuffled_arcana, nrow = 5, ncol = 5))

shuffled_arcana is a factored vector but you cannot have a factor-matrix so it changes the vector from factor to character and hence, sorting does not happen as desired.

Here's a way -

set.seed(2022)

arcanaVector <- c(rep("Supreme", 3),
rep(c("Good", "Moderate", "Poor", "Awful"), each = 5),
rep("Worst", 2))
arcanaLevels <- c("Supreme", "Good", "Moderate", "Poor", "Awful", "Worst")
shuffled_arcana <- sample(arcanaVector)
arcana_table <- matrix(shuffled_arcana,nrow = 5, ncol = 5)
row.names(arcana_table) <- c("Presence", "Manner", "Expression", "Complexity", "Tradition")

arcana_table <- apply(arcana_table, 1, function(x) sort(factor(x, arcanaLevels))) |>
t() |>
as.data.frame()

arcana_table

# V1 V2 V3 V4 V5
#Presence Good Good Good Good Awful
#Manner Supreme Moderate Poor Awful Awful
#Expression Supreme Supreme Moderate Moderate Poor
#Complexity Moderate Moderate Poor Poor Worst
#Tradition Good Poor Awful Awful Worst

If you want to change a specific row you may use -

arcana_table[1, ] <- as.character(sort(factor(arcana_table[1, ], arcanaLevels))) 


Related Topics



Leave a reply



Submit