Reputation: 3207
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)
Upvotes: 2
Views: 5328
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