Reputation: 93
big_theme <- theme(
panel.background = element_rect(fill = "black"),
plot.background = element_rect(fill = "black", colour = NA),
plot.title = element_text(hjust = 0.5, size = 15, color = "white"),
axis.text.y = element_text(colour = "white", size = 14),
axis.title.x = element_text(colour = "white", size = 14),
axis.title.y = element_text(colour = "white", size = 14),
axis.text.x = element_text(vjust = 1, angle = 45, color = "white", size = 14, hjust=1),
strip.background = element_rect(fill = "black"),
strip.text = element_text(colour = 'white'),
strip.text.y = element_text(angle = 0),
legend.position = "top"
)
theme2 = theme(panel.background = element_rect(fill = 'black'),
legend.background=element_rect(fill = "black"),
legend.text = element_text(colour = "white", size = 14),
legend.justification = "right",
legend.key.height = unit(1, "line"),
legend.key = element_rect(color = "black", fill = "black"))
theme3 = theme(plot.background = element_rect(fill = 'black'))
plot1 <- ggplot(sample_data) + big_theme + theme2 + theme3
plot1 +
geom_col(position = "identity",
aes(x = category, y = value,
fill = forcats::fct_relevel(variable, c("z", "x", "y")),
color = forcats::fct_relevel(variable, c("z", "x", "y")))) +
scale_fill_manual(values = c("#000000","#D3667C","#53AC79")) +
scale_color_manual(values = c("#00A2EF","#D3667C","#53AC79")) +
geom_text(aes(label = big_category, x = big_category, y = 0), vjust = 0,
size = 3, color = "white", position = position_dodge(width = 1)) +
scale_y_continuous(limits = c(0, 2.4), expand = c(0, 0))
I have a dataset that looks like:
big_category category variable value
a aa x 1.2
a ba x 1.05
a ca x 1.11
a aa y 1.43
a ba y 1.09
a ca y 0.97
a aa z 1.12
a ba z 1.46
a ca z 1.32
b ab x 1.2
b bb x 1.05
b cb x 1.11
b ab y 1.43
b bb y 1.09
b cb y 0.97
b ab z 1.12
b bb z 1.46
b cb z 1.32
c ac x 1.2
c ac y 1.05
c ac z 1.11
I want the x-axis to be labeled by category and below that I want labels for big_category. For example, I want axis labels for aa,ba, and ca, and then one label below that for big_category a in the ggplot. I dont want it mixed in with the labels for category and I also want it underneath the x-axis labels displayed horizontally.
I've also tried facet_grid but that gives me a problem, as the bars aren't evenly sized. Like big_category a has 3 categories but big_category c has only 1. I want all of them to have the same width, and I want one continuous plot.
Update
big_category category variable value
a aa111111111 x 1.2
a ba111111111 x 1.05
a ca111111111 x 1.11
a aa111111111 y 1.43
a ba111111111 y 1.09
a ca111111111 y 0.97
a aa111111111 z 1.12
a ba111111111 z 1.46
a ca111111111 z 1.32
b ab111111111 x 1.2
b ab111111111 y 1.05
b ab111111111 z 1.11
c ac111111111 x 1.2
c bc111111111 x 1.05
c cc111111111 x 1.11
c ac111111111 y 1.43
c bc111111111 y 1.09
c cc111111111 y 0.97
c ac111111111 z 1.12
c bc111111111 z 1.46
c cc111111111 z 1.32
Code:
big_theme <- theme(
panel.background = element_rect(fill = "black"),
plot.background = element_rect(fill = "black", colour = NA),
plot.title = element_text(hjust = 0.5, size = 15, color = "white"),
axis.text.y = element_text(colour = "white", size = 14),
axis.title.x = element_text(colour = "white", size = 14),
axis.title.y = element_text(colour = "white", size = 14),
axis.text.x = element_text(vjust = 1, angle = 45, color = "white", size = 14, hjust=1),
strip.background = element_rect(fill = "black"),
strip.text = element_text(colour = 'white'),
strip.text.y = element_text(angle = 0),
legend.position = "top"
)
theme2 = theme(panel.background = element_rect(fill = 'black'),
legend.background=element_rect(fill = "black"),
legend.text = element_text(colour = "white", size = 14),
legend.justification = "right",
legend.key.height = unit(1, "line"),
legend.key = element_rect(color = "black", fill = "black"))
theme3 = theme(plot.background = element_rect(fill = 'black'))
ggplot(sample_data %>% mutate(variable=fct_relevel(variable, c("z","x","y")))) +
geom_col(position = "identity",
aes(x = category, y = value, fill = variable, color = variable)) +
facet_grid(. ~ big_category, space="free_x", scales="free_x", switch="x") +
big_theme + theme2 + theme3 +
theme(strip.placement = "outside",
strip.background = element_rect(fill=NA,colour="white"),
panel.spacing.x=unit(0,"cm"),
strip.text = element_text(hjust=0, face="bold", size=12))
Upvotes: 4
Views: 7390
Reputation: 93811
Below is an example, using your sample data, of how to have category
within big_category
. I've included only the essential plot elements for simplicity. You can, of course, add your specific theme, colors, and other elements to the basic plot below.
library(tidyverse)
ggplot(sample_data %>% mutate(variable=fct_relevel(variable, c("z","x","y")))) +
geom_col(position = "identity",
aes(x = category, y = value, fill = variable, color = variable)) +
facet_grid(. ~ big_category, space="free_x", scales="free_x", switch="x") +
theme_classic() +
theme(strip.placement = "outside",
strip.background = element_rect(fill=NA, colour="grey50"),
panel.spacing.x=unit(0,"cm"))
UPDATE: If I understand your comment, here's updated code to left-justify the strip text and remove the strip borders. I don't know of a way (without hacking the underlying graphical objects outside of ggplot) to have just vertical lines between strips. However, I've added back a bit of space between panels and added panel borders to delineate the big_category
levels.
ggplot(sample_data %>% mutate(variable=fct_relevel(variable, c("z","x","y")))) +
geom_col(position = "identity",
aes(x = category, y = value, fill = variable, color = variable)) +
facet_grid(. ~ big_category, space="free_x", scales="free_x", switch="x") +
theme_bw() +
theme(strip.placement = "outside",
strip.background = element_rect(fill=NA,colour=NA),
panel.spacing.x=unit(0.15,"cm"),
strip.text = element_text(hjust=0, face="bold", size=12))
UPDATE 2: I've created a plot with the following changes: (1) big_category
labels at the left end of the x-axis labels, and (2) blank big_category
labels when category
has less than 3 unique levels. To keep the same facet "breaks" with blank labels, we create a unique white-space string (by varying the length of the string) for each former big_category
value.
I don't think the plot looks very good (I actually think it would work better with the big_category
facet strips on top in their standard position and with the text centered), but perhaps you can play around with it and get something that meets your needs. I've commented the code to explain what it's doing, but let me know if anything is unclear.
We'll use the new sample_data
you posted, but we'll add a fourth level to big_category
:
sample_data = sample_data %>%
bind_rows(data_frame(big_category="d",
category=c("da1111111111", "db111111"),
variable=c("z","x"), value=c(1.1,0.6)))
Now we'll make a few transformations of sample_data
to set it up for plotting and pipe the adjusted data frame right into ggplot:
sample_data %>%
mutate(variable=fct_relevel(variable, c("z","x","y"))) %>%
# Create grouping column (called short_cat) to mark levels of big_category
# with two or fewer unique levels of category
group_by(big_category) %>%
mutate(short_cat = length(unique(category)) <= 2) %>%
ungroup %>%
# Create a unique white-space string for each unique value of grp
mutate(grp = c(0, cumsum(diff(short_cat) != 0)),
grp = sapply(grp, function(g) paste(rep(" ", g), collapse="")),
# Assign white-space strings to each level of big_category for which short_cat
# is TRUE
big_category=replace(big_category, short_cat, grp[short_cat]),
# Set factor order for big_category so new levels will stay in same order
# as original levels
big_category=factor(big_category, levels=unique(big_category))) %>%
ggplot() +
geom_col(position = "identity", width=0.8,
aes(x = category, y = value, fill = variable, color = variable)) +
facet_grid(. ~ big_category, space="free_x", scales="free_x", switch="x") +
theme_bw() +
theme(axis.text.x=element_text(angle=45, vjust=1, hjust=1),
strip.placement = "outside",
strip.background = element_rect(fill=NA,colour=NA),
panel.spacing.x=unit(0.15,"cm"),
# Left justify big_category labels
strip.text = element_text(hjust=0, face="bold", size=12)) +
# Expand left side of x-axis so that big_category labels will be under left
# end of x-axis labels
expand_limits(x=-0.5)
Upvotes: 10