Controlling Order of Facet_Grid/Facet_Wrap in Ggplot2

controlling order of facet_grid/facet_wrap in ggplot2?

I don't think I can really satisfy your "without making a new data frame" requirement, but you can create the new data frame on the fly:

ggplot(transform(iris,
Species=factor(Species,levels=c("virginica","setosa","versicolor")))) +
geom_histogram(aes(Petal.Width))+ facet_grid(Species~.)

or, in tidyverse idiom:

iris %>%
mutate(across(Species, factor, levels=c("virginica","setosa","versicolor"))) %>%
ggplot() +
geom_histogram(aes(Petal.Width))+
facet_grid(Species~.)

I agree it would be nice if there were another way to control this, but ggplot is already a pretty powerful (and complicated) engine ...

Note that the order of (1) the rows in the data set is independent of the order of (2) the levels of the factor. #2 is what factor(...,levels=...) changes, and what ggplot looks at to determine the order of the facets. Doing #1 (sorting the rows of the data frame in a specified order) is an interesting challenge. I think I would actually achieve this by doing #2 first, and then using order() or arrange() to sort according to the numeric values of the factor:

neworder <- c("virginica","setosa","versicolor")
library(plyr) ## or dplyr (transform -> mutate)
iris2 <- arrange(transform(iris,
Species=factor(Species,levels=neworder)),Species)

I can't immediately see a quick way to do this without changing the order of the factor levels (you could do it and then reset the order of the factor levels accordingly).

In general, functions in R that depend on the order of levels of a categorical variable are based on factor level order, not the order of the rows in the dataset: the answer above applies more generally.

Fixing the order of facets in ggplot

Make your size a factor in your dataframe by:

temp$size_f = factor(temp$size, levels=c('50%','100%','150%','200%'))

Then change the facet_grid(.~size) to facet_grid(.~size_f)

Then plot:
Sample Image

The graphs are now in the correct order.

R Changing Order of Facets


dfx$group <- factor(dfx$group, levels = c("SLG","BA"))

Is it possible to reorder only the facets of facet_wrap, without reordering the underlying factor levels?

Copy the data into a new column with the order you want. Use the new column for faceting, the old column for the the color.

df$facet = factor(df$Case, levels = c("L", "B", "R", "BC"))

ggplot(df, aes(x = x, y = y, color = Case)) +
geom_line() +
facet_wrap(~facet, nr = 2)

Ordering of ggplot2 facets changes after adding to a facet

The dataframe for the line, column drv must have same factor levels as original dataframe mpg2:

p + geom_hline(data = data.frame(xint = 20, 
drv = factor("r", levels = levels(mpg2$drv))),
aes(yintercept = xint), linetype = "dotted", color = "blue")

Sample Image

Reformat label / preserve order of Multi-factor facets in ggplot2::facet_wrap() based on factor level

Wow, that was a lot trickier than I expected... One solution would be to combine them into a different field:

tmp.d |> 
arrange(sector, subsector) |> # arrange by factor levels
mutate(
facet =
paste0(sector, ": ", subsector) |>
fct_inorder(ordered = TRUE) # use that order for the new field
) |>
ggplot(aes(x = year, y = value, group = 1)) +
geom_path()+
facet_wrap(facets = ~facet) # here

This also works if a ", " is acceptable:

ggplot(tmp.d, aes(x = year, y = value, group = 1)) +
geom_path()+
facet_wrap(
facets = sector~subsector,
labeller =
labeller( # here
sector = label_value, #
subsector = label_value, #
.multi_line = FALSE #
)
)

A similar thing can be done with purrr::partial() which substitutes out defaults but again you get a comma. I think it would be worth creating an issue on their github page to add a sep argument to the label_*() functions

... +
facet_wrap(
facets = sector~subsector,
labeller = purrr::partial(label_value, multi_line = FALSE)
)

Order facet_wrap plots by descending order

You can reorder the factor levels of C according to the values of B (in descending order) using forcats::fct_reorder or base reorder inside the facet_wrap:

library(tidyverse)

## data
M <- data.frame(
A = LETTERS[1:10],
B = round(rnorm(10,200,50)),
C = letters[15:24]
)

## using fct_reorder
ggplot(M, aes(x = A, y = B)) +
geom_bar(stat = "identity") +
facet_wrap(facets = ~fct_reorder(C, B, .desc = TRUE))

## using base reorder
ggplot(M, aes(x = A, y = B)) +
geom_bar(stat = "identity") +
facet_wrap(facets = ~reorder(C, -B)) ## -B to get descending order

Sample Image

Reordering plots when using facet_wrap and gather

Try reordering the levels of the factor you use for facetting:

df$key <- factor(df$key, levels=c("first facet", "second facet", (in the order you want the facets))

Note that this will be cleaner if you assign your gathered data frame to a variable, then reorder the facets, then call ggplot.

order a facet_grid or facet_wrap grid by modality in ggplot2

You can try using an interaction eg pasting both variables together.

library(tidyverse)
# Calculate the maximum on both values
gr <- my.df %>%
mutate(group=paste(use, es.type, sep="\n")) %>%
group_by(group) %>%
summarise(Max=sum(value)) %>%
arrange(-Max)

# Plot the data, but specifiying the order of the facets via
# the factor levels with respect to the order in `gr`.
my.df %>%
mutate(group=factor(paste(use, es.type, sep="\n"), levels=gr$group)) %>%
ggplot()+
geom_bar(aes(x = site, y = value, fill = site), stat="identity")+
facet_wrap(~group)+
theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank())

Sample Image

--

In base R you can do before plotting:

my.df$group <- paste(my.df$use, my.df$es.type, sep="\n")
gr <- aggregate(value ~ group, my.df, sum)
gr <- gr[order(gr$value, decreasing = T), ]
my.df$group <- factor(my.df$group, levels = gr$group)


Related Topics



Leave a reply



Submit