2

I'm attempting to layer a scatter plot (with error bars) over a stacked bar plot in R which is intended as a heat map style backfill, to visually show which categories the points fall into. I've built both components successfully, but can't seem to combine them successfully, or to find a similar example to draw from.

Edited to add: That after stripping the code down to a ggplot()+ geom structure for both graphs and removing the error bars I can get both on the same graph, but the scale is off (though both have a ymax=35) and I can not get them to overlap.

     ##library/packages

library(reshape2)
library(ggplot2)
library(forcats) #forcats package
library(scales)
library(plyr)
library(ggplot2)

#Data for point graph:
df<-data.frame(Location=c("Location1","Location2", "Location3"), WALL=c(3.5,1.6,30), NRPK=c(5.6,1.0,21), WALL_CL_L=c(3.2,1.5,27),
               WALL_CL_U=c(3.8,2.0,32), NRPK_CL_L=c(5.0,0.05,19.3), NRPK_CL_U=c(6.1,1.2,23.5))
xWALL<-subset(df, select=c("Location","WALL","WALL_CL_L","WALL_CL_U"))

#Data for bar graph:
dat <- read.table(text = "     FSI_Scale
                  1   6
                  2   9
                  3   7
                  4   8
                  5   5",sep = "",header = TRUE)

datm <- melt(cbind(dat, ind = rownames(dat)), id.vars = c('ind'))

MyColours<-c('green3','green2','yellow1','orange1','red')

Basic<- ggplot() +
  geom_point(data=xWALL, aes(x=Location, y=WALL), size=2, shape=23, color="black", fill="cornflowerblue") +
  geom_bar(data=datm, aes(x=variable, y=value, fill=forcats::fct_rev(ind)), stat = "identity", position = "fill", width = 1) + scale_fill_manual(values = MyColours)+
  theme(axis.title=element_blank(), axis.text=element_blank(),axis.ticks=element_blank())+
  guides(fill=FALSE)+
  scale_y_continuous(limits=c(0,35))

The result is this:barandpoint

Thank you very much for any help you can provide.

randomr
  • 21
  • 1
  • 5
  • 1
    This is a lot of text/code! Can you please edit your post to make your question more succinct; best to give a *minimal (!) reproducible example* with sample data, describing what you tried and what your expected outcome is. See [here on how to provide a minimal reproducible example/attempt](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) if unsure. – Maurits Evers Feb 18 '18 at 06:32
  • 1
    I've edited the post to be more succinct. I don't really know how to compress the code more since I can't work out precisely what's giving me the error -- as I try to mesh the two graphs different ways new error messages pop up. Sometimes it seems to be problems with aes, sometimes it's as if data parameters get lost. If my question is inappropriate I'll be happy to remove it though. – randomr Feb 18 '18 at 07:02

2 Answers2

0

You are getting the error message ggplot2 doesn't know how to deal with data of class uneval because you are trying to combine plots without first defining where the data is coming from. This is the correct way to plot it using your code:

p<- ggplot() +
  geom_point(data=xWALL, aes(x=Location, y=WALL), size=2, shape=23, color="black", fill=Loccolors) +
  geom_errorbar(data=xWALL, aes(ymax=WALL_CL_U, ymin=WALL_CL_L), width=0.05, size=0.1) +
  scale_y_continuous(limits=c(0,35),expand=c(0,0))+
  theme_bw()+
  theme_classic()+
  axis.line = element_line(color = 'black')+
  geom_bar(data = datm, aes(x=variable, y=value, fill=forcats::fct_rev(ind)), position = "fill",stat = "identity", width = 1) + scale_fill_manual(values = MyColours)+
  theme(axis.title=element_blank(), axis.text=element_blank(),axis.ticks=element_blank())+
  guides(fill=FALSE)+
  scale_y_continuous(labels = percent_format())

This should work but because you haven't produced a MRE, I'm honestly too lazy to go through the code. Try to remove any unnecessary code such as when dataframes are printed to console or in your plots, drop theme_bw()+ theme_classic() because that's not important.

Amar
  • 1,340
  • 1
  • 8
  • 20
  • 1
    MRE? I'm sorry, but I can't find a meaning for that abbreviation (and I'm not a native English speaker, so I can't work it out). The class uneval error message isn't associated with that code permutation, it's "Error, don't know how to add o to the plot" (it's a o not a 0). I tried your suggestion and got a different error message:"Error in percent_format() : could not find function "percent_format"". I haven't listed all of the error messages because I don't get just one, it changes with everything I try. This is what makes me think it might not be possible. Thanks for the help. – randomr Feb 18 '18 at 07:53
  • 1
    @randomr MRE = minimal reproducible example – Maurits Evers Feb 18 '18 at 09:48
  • 1
    Thanks, I didn't think you meant military rations, but that was the only abbreviation I knew. As for an MRE, don't the pieces of code count? If you run the two graphs they work, and the data's included. If you try my two attempts at getting the merged graph to work they don't. I frankly don't know how else to express it, but that could be language (and unfamiliarity with coding) affecting my understanding. Thanks for your time in any case, and the explanation. – randomr Feb 18 '18 at 14:44
  • 1
    @randomr, the keyword here is *minimal*---you included a lot of unnecessary code. I notice you have a lot of visual tweaking, e.g. adding themes, axis labels, etc. These are not necessary to pose a question about plot structure, but discourage people from answering because it looks like a wall of code. – mikeck Feb 18 '18 at 15:55
  • @mikeck11 This is part of what I'm not grasping, I'm afraid, because to me the way the graphs look is part of the reason they won't combine (i.e. one is a percentage and a bar, the other is just straight values as points). I've just edited my question because I got the two graphs to combine, but it's still not functional. I've removed the earlier non-functional code, though, so hopefully that will clarify things. I can tear out the examples of how the two layers are supposed to look as well if that will help. Thanks. – randomr Feb 18 '18 at 16:12
  • Hmm, that might be true but in my opinion that is very unlikely. A lot of the errors you are getting is probably due to things that change the axis, for example: `labels = percent_format()`. these are not only important but required for your specific requirements. The others? No, they are probably useless. Anyway, even if they are causing the error, you should remove them all and add them in one at a time and stop when you see the error. Btw, you're seeing the error irrespective of those settings. – Amar Feb 18 '18 at 22:59
  • @Amar Thanks. I've been picking my way through learning R piecemeal so I don't necessarily know what is and isn't needed. I ended up solving the problem by trying a different approach. Thanks for the help, and sorry for the long delay. For some reason your comment didn't register. – randomr Mar 08 '18 at 04:59
  • Glad a could help. Mark it as an answer if you think it's correct:) – Amar Mar 08 '18 at 05:22
0

I ended up answering my own question. The necessary step was to make a very basic heat map (instead of a bar plot) and overlay the points:

library(RColorBrewer)
library(ggplot2)
#heat map dataframe
d<-data.frame(x=c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2), y=rep(0:25,2), z=c(1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,4,4,4,4,5,5,5,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,4,4,4,4,5,5,5), w=rep(2,52))
#data point dataframe
pd<-data.frame(Loc=c(1,2), var=c(11,17))
#colour palette for heat map
colfunc<-colorRampPalette(c("red","darkorange","yellow1","springgreen","springgreen3"))

ggplot() +
  geom_tile(data=d, aes(x,y, fill = z), show.legend=FALSE)  +
  scale_fill_gradientn(colours = colfunc(5)) +
  scale_x_continuous(expand = c(0, 0)) + 
  scale_y_continuous(breaks=pretty(d$y, n=10),expand = c(0, 0)) + #point after heatmap or it will be covered
  geom_point(data=pd,aes(Loc, var))+
  theme_bw() +
  theme(axis.title.x =element_blank(),
        axis.title.y=element_blank(),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(), 
        panel.border = element_blank(),
        panel.background = element_blank()) 

This allows the heat map to be adjusted to show different thresholds as needed, and show where data falls relative to them.

randomr
  • 21
  • 1
  • 5