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:
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
Count Number of Rows Per Group and Add Result to Original Data Frame
How to Call an Object With the Character Variable of the Same Name
Count Number of Rows in a Data Frame in R Based on Group
Strptime, As.Posixct and As.Date Return Unexpected Na
How to Make a List of Data Frames
Grouping Functions (Tapply, By, Aggregate) and the *Apply Family
Reshaping Multiple Sets of Measurement Columns (Wide Format) into Single Columns (Long Format)
Sort (Order) Data Frame Rows by Multiple Columns
Ggplot With 2 Y Axes on Each Side and Different Scales
Simultaneously Merge Multiple Data.Frames in a List
Repeat Each Row of Data.Frame the Number of Times Specified in a Column
Explicitly Calling Return in a Function or Not
Why Are These Numbers Not Equal
Cleaning Up Factor Levels (Collapsing Multiple Levels/Labels)
Looping Over a Date or Posixct Object Results in a Numeric Iterator