Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding points from other dataset to ggplot2

Tags:

r

ggplot2

There are already many questions about this theme, but I could not find one that answered my specific problem.

I have a barplot (see testplot1 and testplot3 below) plotting a dataset (bardata below) and want to add points to it from another dataset (pointdata). See the simplified example:

bardata <- data.frame(
               xname = c(1, 1, 1, 2, 2, 2, 3, 3, 3), 
               yvalue = c(1, 2, 3, 2, 3, 1, 4, 2, 1), 
               colorname = c("a", "b", "c", "a", "b", "c", "a", "b", "c")
               )  
pointdata <- data.frame(
                xname = c(1, 1, 3), 
                ypos = c(2, 4, 3), 
                ptyname = c("p", "q", "r")
             ) 

testplot1 <- qplot(xname, yvalue, data= bardata, stat = "identity", 
               fill= factor(colorname),  geom = "bar")
testplot2 <- testplot1 + 
                geom_point(data = pointdata, mapping = 
                  aes(x = xname, y = ypos, shape = factor(ptyname))
                )

Now testplot1 works perfectly fine, but testplot2 gives the error

Error in factor(colorname) : object 'colorname' not found.

I do not understand why he says this, and would like to know, but this is not my main problem since there is an easy workaround, see testplot3 below.

 testplot3 <- qplot(xname, yvalue, data= bardata, stat = "identity", 
                      fill= factor(bardata$colorname),  geom = "bar")
 testplot4 <- testplot3 + 
                  geom_point(data = pointdata, mapping = 
                    aes(x = xname, y = ypos, shape = factor(ptyname)))

Now this time the program says:

Error: Aesthetics must either be length one, or the same length as the dataProblems:xname, ypos, factor(ptyname).

So my question is: what does this even mean? Obviously both aes and the data are of length 3. The number of rows in pointdata is less than that in bardata, but that is in itself not a problem, see for instance this answer: https://stackoverflow.com/a/2330825/2298323

So what is going on here? (And how do I get my points in my plot?)

like image 878
Vincent Avatar asked Jun 26 '15 09:06

Vincent


2 Answers

The issue is that you are assigning fill = factor(colorname)for the whole plot in your qplot call.

So testplot2 will also try to map colorname to the fill aesthetic but there is no colorname column in the pointdata data.frame which is why you have this error message. If you rewrite it using ggplot, it looks like this :

ggplot(bardata, aes(xname, yvalue, fill = factor(colorname))) +
  geom_bar(stat = "identity")+ 
  geom_point(data = pointdata, 
             mapping = aes(x = xname, y = ypos, shape = factor(ptyname)))

What you need to do is to apply the mapping only to the geom_bar call, like this :

ggplot(bardata, aes(xname, yvalue)) +
  geom_bar(stat = "identity", aes(fill = factor(colorname)))+ 
  geom_point(data = pointdata, 
             mapping = aes(x = xname, y = ypos, shape = factor(ptyname)))
like image 181
Tutuchan Avatar answered Oct 05 '22 20:10

Tutuchan


Yeah, sometimes ggplot error descriptions are quite difficult to understand. First note: try to avoid qplot, for rather complicated plots it tends to obscure things. Your code is equivalent to

ggplot(bardata, aes(xname, yvalue, fill = factor(colorname))) + 
  geom_bar(stat = "identity") + 
  geom_point(data = pointdata, aes(x = xname, y = ypos, shape = factor(ptyname))

#Error in factor(colorname) : object 'colorname' not found

And here's the problem: when you specify aes mapping within ggplot() (or qplot() in your case), this setting is automatically applied to any subsequent geom. You specified x, y and fill. For geom_bar, everything is okay. For geom_point you override x and y, but the fill is still mapped to colorname which doesn't exist in pointdata, therefore the error.

If you mix several data frames, here's the recommended way to go: empty ggplot() plus specific aes for each geom.

ggplot() + 
  geom_bar(data = bardata, aes(xname, yvalue, fill = factor(colorname)), stat = "identity") + 
  geom_point(data = pointdata, aes(xname, ypos, shape = factor(ptyname)))

enter image description here

like image 36
tonytonov Avatar answered Oct 05 '22 19:10

tonytonov