Reputation: 407
I have a dataframe of overnight stays per holiday location by origin-location, year and age group, which is plotted in ggplot, facetted by Year and age group:
As you can see, the lines don't sort correctly from smallest to largest. I use 'reorder_within' and 'scale_x_reordered' by Tyler Rinker, and it works like a charm when data is only faceted by one variable, e.g. Year or age_group, but not both, which is what I'd like.
Reproducible example including dummy data below:
library(tidyverse)
library(scales)
reorder_within <-
function(x,
by,
within,
fun = mean,
sep = "___",
...) {
new_x <- paste(x, within, sep = sep)
stats::reorder(new_x, by, FUN = fun)
}
scale_x_reordered <- function(..., sep = "___") {
reg <- paste0(sep, ".+$")
ggplot2::scale_x_discrete(
labels = function(x)
gsub(reg, "", x),
...
)
}
dummy_f <- data.frame(
Eco_T = rep("dest101", 65),
Eco_Code = rep(101, 65),
Year = c(2018,2018,2019,2020,2019,2020,2018,2020,2021,2019,2021,2018,2021,2021,
2020,2021,2019,2019,2018,2018,2019,2021,2020,2019,2019,2019,2019,
2019,2020,2018,2021,2020,2021,2021,2021,2019,2021,2021,2018,2019,2018,
2020,2020,2018,2020,2019,2018,2020,2021,2020,2021,2018,2019,2021,2019,
2020,2021,2020,2020,2018,2018,2021,2019,2021,2018),
age_groups = c(
"under35","over35","under35","under35","over35","under35","over35",
"under35","under35","under35","under35","under35","over35","over35",
"under35","under35","over35","over35","under35","over35","under35",
"over35","over35","under35","over35","under35","over35",
"over35","over35","under35","under35","over35","over35","over35","under35",
"under35","over35","over35","over35","over35","under35",
"over35","under35","over35","over35","over35","over35","over35",
"over35","under35","under35","over35","over35","under35", "over35",
"over35","over35","under35","over35","over35","over35","over35","under35",
"over35","over35"
),
origin_Code = c(
30301030,30303030,30305030,30301030,30301030,70701070,30303030,31314031,
30301030,30301030,30304030,31311031,30301030,30301030,30309030,30304030,
31314031,30301030,30301030,30301030,30301030,30303030,31316031,30301030,30301030,
30309030,30302030,31317031,30301030,30303030,30309030,
30309030,30309030,30303030,31310031,11110011,30309030,30305030,31314031,
30309030,30309030,30301030,30304030,30301030,30301030,30304030,30303030,
30309030,31314031,30305030,30301030,30302030,31313031,30305030,30302030,
31316031,30309030,30301030,31316031,30302030,31313031,31316031,30309030,
30301030,30301030
),
Origin_Name = c(
"Wyumwym","Candcar","Brababri","Wyumwym","Wyumwym","Lihflit","Matramt",
"Thithe","Calacap","Wyumwym","Shwoshe","Brnsbro","Clelecle","Calacap",
"Brdabro","Keorken","Thithe","Clelecle","Clelecle","Calacap","Clelecle","Candcar",
"Cauncal","Calacap","Calacap","Brdabro","Sagasan",
"Tooto","Clelecle","Candcar","Coancoo","Orauorm","Hoanhol","Fostfor",
"Inreive","Gocgol","Brababri","Thithe","Brababri","Orauorm","Mueemud",
"Calacap","Shwoshe","Wyumwym","Wyumwym","Keorken","Hoanhol","Gocgol",
"Thithe","Brababri","Wyumwym","Sagasan","Relired","Brababri","Chemsche",
"Suhisun","Brdabro","Calacap","Maochmar","Chemsche","Relired","Cauncal","Ronarob",
"Wyumwym","Clelecle"
),
overnight_stays = c(
266,132,158,143,964,78,134,47,45,130,94,42,500,105,95,590,5666,106,324,
412,99,433,511,54,506,46,471,48,254,5257,51,388,70,421,662,419,
130,539,60,69,435,135,2146,406,230,413,126,322,782,86,152,162,406,84,458,426,
406,46,426,127,109,626,44,1333,961
)
)
ggplot.object <- dummy_f %>%
ggplot() +
(aes(
x = reorder_within(Origin_Name, -overnight_stays, Year),
y = overnight_stays,
)) + geom_point(size = 4, color = "#374c92") +
geom_segment(
aes(
x = reorder_within(Origin_Name, -overnight_stays, Year),
xend = reorder_within(Origin_Name, -overnight_stays, Year),
y = 0,
yend = overnight_stays
),
color = "#374c92",
size = 2
) +
scale_x_reordered() +
scale_color_distiller(type = "seq", palette = "BuPu", direction = 1,
limits = c(-5, NA)) +
facet_wrap(
age_groups ~ Year,
dir = "v",
scales = "free",
ncol = 2
) +
scale_y_continuous(labels = comma) +
labs(y = "Unique Agents",
x = "") +
theme(
panel.spacing.y = unit(10, units = "mm"),
text = element_text(family = "sans-serif",
color = "#B6BAC3"),
axis.text = element_text(color = "#B6BAC3",
size = 8),
axis.title = element_text(color = "#B6BAC3",
size = 12),
axis.line = element_line(color = "#B6BAC3"),
strip.text = element_text(size = 15,
color = "#B6BAC3"),
legend.position = "none",
panel.background = element_rect(fill = "transparent",
color = NA),
plot.background = element_rect(fill = "transparent",
color = NA),
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()
) +
coord_flip()
ggplot.object
Upvotes: 3
Views: 641
Reputation: 17079
We can modify reorder_within()
to accept an arbitrary number of "within" variables by replacing the within
argument with dots:
reorder_within2 <- function(x,
by,
...,
fun = mean,
sep = "___") {
new_x <- paste(x, ..., sep = sep)
stats::reorder(new_x, by, FUN = fun)
}
Then pass all facet levels to ...
:
ggplot.object <- dummy_f %>%
ggplot() +
aes(
x = reorder_within2(Origin_Name, -overnight_stays, Year, age_groups),
y = overnight_stays,
) +
geom_point(size = 4, color = "#374c92") +
geom_segment(
aes(
xend = reorder_within2(Origin_Name, -overnight_stays, Year, age_groups),
y = 0,
yend = overnight_stays
),
color = "#374c92",
size = 2
) +
# rest of code unchanged from original:
scale_x_reordered() +
scale_color_distiller(type = "seq", palette = "BuPu", direction = 1,
limits = c(-5, NA)) +
facet_wrap(
age_groups ~ Year,
dir = "v",
scales = "free",
ncol = 2
) +
scale_y_continuous(labels = comma) +
labs(y = "Unique Agents",
x = "") +
theme(
panel.spacing.y = unit(10, units = "mm"),
text = element_text(family = "sans-serif",
color = "#B6BAC3"),
axis.text = element_text(color = "#B6BAC3",
size = 8),
axis.title = element_text(color = "#B6BAC3",
size = 12),
axis.line = element_line(color = "#B6BAC3"),
strip.text = element_text(size = 15,
color = "#B6BAC3"),
legend.position = "none",
panel.background = element_rect(fill = "transparent",
color = NA),
plot.background = element_rect(fill = "transparent",
color = NA),
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()
) +
coord_flip()
ggplot.object
The y axis is now ordered smallest to largest within each facet:
Upvotes: 2