DaniCee
DaniCee

Reputation: 3207

Overlay geom_point to geom_bar. How to align the points and bars?

I have been trying this for enough time and I just have to ask... It seems very basic and it has probably been asked before, but I cannot find any post that applies to my particular situation.

Really simple, I have 2 data frames with the same grouping variables but different data I want to plot together, one as bars, and another as points on top.

I am using mtcars for this example. I have my ID variables as the car model, then I use two grouping variables carb and cyl that are in both my data frames.

One data frame has the max disp value per carb and cyl so it's shorter (I filled in missing values as 0 for all the carb-cyl combinations); I want to plot it as bars.

The other data frame has the individual disp values per model, and I want to plot it on top as points.

This is my approach, but the resulting plot is really wrong, the colors and points positions need to be adjusted there... Ideally I would like all points to be black, but I seem to only have them separated by group if I do color. For the positioning, it goes inside a function so should work for any number of levels in the data frame grouping variables.

mtcars$model <- rownames(mtcars)
mtcars$cyl <- as.factor(as.character(mtcars$cyl))
mtcars$carb <- as.factor(as.character(mtcars$carb))

mydf1 <- as.data.frame(data.table::data.table(mtcars)[, list(max=max(disp)), by=list(cyl=cyl, carb=carb)])

mydf2 <- mtcars[,c(2,3,11,12)]
zerodf <- expand.grid(cyl=unique(mtcars$cyl), carb=unique(mtcars$carb))

mydf1 <- merge(mydf1, zerodf, all=TRUE)
mydf1$max[which(is.na(mydf1$max))] <- 0

P <- ggplot2::ggplot(data=NULL) +
  ggplot2::geom_bar(data=mydf1, ggplot2::aes(carb, max, fill=cyl), position="dodge", stat="identity") +
  ggplot2::scale_fill_manual(values=c("blue","red","grey"))

P <- P + ggplot2::geom_point(data=mydf2, ggplot2::aes(carb, disp, color=cyl), position=ggplot2::position_dodge(width=0.5), shape=3, size=5, show.legend=FALSE)

test

Upvotes: 2

Views: 5328

Answers (1)

stefan
stefan

Reputation: 124183

The simple issue is the coloring of the points. To get black points simply map cyl on the group aesthetic in the geom_point layer. The tricky part is the positioning. To get the positioning of the points right you have to fill up mydf2 to include all combinations of cyl and carb as you have already done for mydf1. To this end I use tidyr::complete. Try this:

library(ggplot2)

mtcars$model <- rownames(mtcars)
#head(mtcars)

mtcars$cyl <- as.factor(as.character(mtcars$cyl))
mtcars$carb <- as.factor(as.character(mtcars$carb))
#summary(mtcars)
mydf1 <- as.data.frame(data.table::data.table(mtcars)[, list(max=max(disp)), by=list(cyl=cyl, carb=carb)])

mydf2 <- mtcars[,c(2,3,11,12)]

zerodf <- expand.grid(cyl=unique(mtcars$cyl), carb=unique(mtcars$carb))
mydf1 <- merge(mydf1, zerodf, all=TRUE)
mydf1$max[which(is.na(mydf1$max))] <- 0

mydf2 <- tidyr::complete(mydf2, carb, cyl)

ggplot(data = NULL, aes(group = cyl)) +
  geom_bar(data=mydf1, aes(carb, max, fill=cyl), position="dodge", stat="identity") +
  scale_fill_manual(values=c("blue","red","grey")) +
  geom_point(data=mydf2, aes(carb, disp, group=cyl), position = position_dodge(width = 0.9), shape=3, size=5, show.legend=FALSE)
#> Warning: Removed 9 rows containing missing values (geom_point).

Upvotes: 4

Related Questions