Bottom line is… this is a hard task and there is no good answer. The three work around I came up with are:
I implemented the last two options here, but the first would be a good choice if it fits your project requirements/goals.
I could not load the qlfs.Rdata files, so I made something similar
obs <- 100
qlfs <- data.frame(YoungestChild = sample(x = c(0:20), size = obs, replace = TRUE ),
Marital.Status = rbinom(obs, 1, 0.8),
AgeGroup = factor(sample(x = c(1:5), size = obs, replace = TRUE )),
Sex = sample(c("m","f"), obs, 0.5))
This is all straight from your script, unaltered
qlfs$YoungestChild[qlfs$YoungestChild < 0] <- NA
breaks <- c(0, 3, 5, 12, 18)
qlfs$AdHoc.YoungestChild <- group.data(qlfs$YoungestChild, breaks=breaks)
table.all <- tally(AdHoc.YoungestChild ~ AgeGroup, data = qlfs, format="percent", margin="joint")
table.valid <- tally(AdHoc.YoungestChild ~ AgeGroup, data = qlfs, format="percent", margin="joint", na.rm = TRUE)
AgeGroup.Total.All <- table.all[nrow(table.all),]
AgeGroup.Total.Valid <- table.valid[nrow(table.valid),]
old.categories <- levels(qlfs$AgeGroup)
weights <- AgeGroup.Total.All / AgeGroup.Total.Valid
new.categories <- weights[1:length(weights)-1]
qlfs$weights <- recode(qlfs$AgeGroup, "
old.categories[1]=new.categories[1];
old.categories[2]=new.categories[2];
old.categories[3]=new.categories[3];
old.categories[4]=new.categories[4]
",
levels=c(new.categories))
qlfs$weights <- as.numeric(as.character(qlfs$weights))
qlfs$invalid.cases <- is.na(qlfs$AdHoc.YoungestChild)
qlfs$invalid.cases2 <- is.na(qlfs$YoungestChild)
qlfs$weights[qlfs$invalid.cases==TRUE] <- NA
qlfs$weights[qlfs$invalid.cases2==TRUE] <- NA
new.categories <- c(levels(qlfs$AdHoc.YoungestChild),"No Response")
qlfs$AdHoc.YoungestChild2 <- recode(qlfs$AdHoc.YoungestChild, " NA='No Response' ", levels=c(new.categories) )
These are like yours, but I reduced the number to 4 (because of simulated data) and I created a fill_manual_final that is a combo of male and female
fill_manual <- c("#006d2c", "#2ca25f", "#6bbea3", "#b2e2e2", "#edf8fb")
fill_manual_male <- c("#045a8d", "#2b8cbe", "#74a9cf", "#bdc9e1")
fill_manual_female <- c("#7a0177", "#c51b8a", "#f768a1", "#fbb4b9")
fill_manual_final <- c(fill_manual_female, fill_manual_male)
your plot unaltered
ggplot(na.omit(qlfs)) +
geom_bar(aes(x=AgeGroup, fill=AdHoc.YoungestChild2, weight=weights)) +
ylab("Total Respondents") +
xlab("Age Groups") +
theme() +
facet_wrap(~Sex) +
scale_fill_manual(values = fill_manual,
name="Reported Age of \n Youngest Child") +
theme(strip.background = element_rect(fill = "light blue"))
Simply made a new column mf_youngest that combines the two factors of interest. The plot then colors by the new factor and the scale_fill_manual calls the combined scale to cover all of the new factors. I am not a huge fan of this, but it most closely approximates your goal. There would have to be some work done on the legend to make it prettier.
# new column
qlfs$mf_youngest <- paste0(qlfs$Sex, "_", qlfs$AdHoc.YoungestChild2)
ggplot(na.omit(qlfs)) +
geom_bar(aes(x=AgeGroup, fill=mf_youngest, weight=weights)) +
ylab("Total Respondents") +
xlab("Age Groups") +
theme() +
facet_wrap(~Sex) +
scale_fill_manual(values = fill_manual_final,
name="Reported Age of \n Youngest Child") +
theme(strip.background = element_rect(fill = "light blue"))
This was taken from the S.O. post linked below. Essentially, use scale_alpha_manual to give an effect of changing colors by Adhoc.YoungestChile2. I added a theme_bw() and took away the grid lines to gussy it up a tad. http://stackoverflow.com/questions/33221794/separate-palettes-for-facets-in-ggplot-facet-grid
ggplot(na.omit(qlfs)) +
geom_bar(aes(x=AgeGroup, fill=Sex, weight=weights, alpha = AdHoc.YoungestChild2)) +
ylab("Total Respondents") +
xlab("Age Groups") +
theme_bw() +
facet_wrap(~Sex) +
scale_fill_manual(values = c("#c51b8a", "#2b8cbe"),
name="Sex of \n Youngest Child") +
scale_alpha_manual(values=c(0.35, 0.55, 0.75, 1),
name="Reported Age of \n Youngest Child") +
theme(strip.background = element_rect(fill = "light blue"),
panel.grid.minor = element_blank(),
panel.grid.major = element_blank())