Search code examples
rcolorsggplot2ggmap

ggplot2/ggmap: Use two-color point markers in both plot and legend


I'm having a dataframe samp, with userid, latitude, longitude, mb. I wanted to plot a map with the points proportional to MB used. I wanted a donut kind of shape in geom_point, so I thought I can use two pch = 20 with varying sizes to get the donut shape of pch. But I am facing some problems in it.

m <- get_map(location=c(lon=median(samp$longitude),lat=median(samp$latitude) ), zoom=10)
print(ggmap(m) + 
        geom_point(aes(x=longitude, y=latitude, size= mb.user), colour="orange", pch = 20, data=samp) + 
        geom_point(aes(x=longitude, y=latitude, size= mb.user), colour="black", pch = 20,  size = 4, data=samp))

but I am getting something like,

enter image description here

The shapes are not even throughout the map. I want the shapes to be even and proportional to mb.user values. But the map here is neither proportional to mb.user or the sizes.

Also the legend is also showing only one color. It isn't showing two colours together. I ideally want to have a donut shaped symbol whose size is proportional to mb.user.

Can anybody help me in finding the mistake I am doing here?

Thanks


Solution

  • If you use a point shape that has a border, you can plot the points just once and it will show up properly in the legend. If you have ggplot2 version 2 installed (latest version is 2.1.0 as of this writing), you can also control the width of the point border using the stroke parameter. You haven't provided a reproducible example, so here's an example using the built-in mtcars data frame:

    ggplot(mtcars, aes(wt, mpg)) +
      geom_point(aes(size=mpg), colour="red", fill="black", shape=21, stroke=1.5) +
      scale_size_area(max_size=4) 
    

    shape=21 is a filled circle with a border (see ?pch for available shapes). colour sets the border color, fill sets the fill color, and stroke sets the border width.

    enter image description here

    Regarding your original code, the black circles are all the same size, because you've overridden size=mb.user by also setting size=4 outside the call to aes. You can't see some of the orange points in cases where the black points are larger than the orange points. If you remove size=4 and do size=0.3*mb.user inside aes, you'll get properly scaled black points inside the scaled orange points.

    However, that still won't solve the legend issue. I don't think there's a way to get a legend with black-inside-orange points using two separate calls to geom_point since there's no way (at least none that I can think of) to create a combined size/color mapping to do that. Using a single call geom_point with a filled marker solves the problem, but I thought I'd try to explain as best I could why your original code wasn't working as you expected.