Search code examples
rggplot2geom-col

ggplot2 geom_points won't colour or dodge


So I'm using ggplot2 to plot both a bar graph and points. I'm currently getting this:enter image description here

As you can see the bars are nicely separated and colored in the desired colors. However my points are all uncolored and stacked ontop of eachother. I would like the points to be above their designated bar and in the same color.

  #Add bars
  A <- A + geom_col(aes(y = w1, fill = factor(Species1)), 
                    position = position_dodge(preserve = 'single'))

  #Add colors
  A <- A + scale_fill_manual(values = c("A. pelagicus"= "skyblue1","A. superciliosus"="dodgerblue","A. vulpinus"="midnightblue","Alopias sp."="black"))

  #Add points
  A <- A + geom_point(aes(y = f1/2.5), 
                      shape= 24, 
                      size = 3,
                      fill = factor(Species1), 
                      position = position_dodge(preserve = 'single'))

  #change x and y axis range
  A <- A + scale_x_continuous(breaks = c(2000:2020), limits = c(2016,2019))
  A <- A + expand_limits(y=c(0,150))

  # now adding the secondary axis, following the example in the help file ?scale_y_continuous
  # and, very important, reverting the above transformation
  A <- A + scale_y_continuous(sec.axis = sec_axis(~.*2.5, name = " "))

  # modifying axis and title
  A <- A + labs(y = " ",
                x = " ")
  A <- A + theme(plot.title = element_text(size = rel(4)))
  A <- A + theme(axis.text.x = element_text(face="bold", size=14, angle=45),
            axis.text.y = element_text(face="bold", size=14))
  #A <- A + theme(legend.title = element_blank(),legend.position = "none")
  #Print plot
  A

When I run this code I get the following error:

Error: Unknown colour name: A. pelagicus In addition: Warning messages: 1: Width not defined. Set with position_dodge(width = ?) 2: In max(table(panel$xmin)) : no non-missing arguments to max; returning -Inf

I've tried a couple of things but I can't figure out it does work for geom_col and not for geom_points.

Thanks in advance


Solution

  • The two basic problems you have are dealing with your color error and not dodging, and they can be solved by formatting your scale_...(values= argument using a list instead of a vector, and applying the group= aesthetic, respectively.

    You'll see the answer to these two question using an example:

    # dummy dataset
    year <- c(rep(2017, 4), rep(2018, 4))
    species <- rep(c('things', 'things1', 'wee beasties', 'ew'), 2)
    values <- c(10, 5, 5, 4, 60, 10, 25, 7)
    pt.value <- c(8, 7, 10, 2, 43, 12, 20, 10)
    df <-data.frame(year, species, values, pt.value)
    

    I made the "values" set for my column heights and I wanted to use a different y aesthetic for points for illustrative purposes, called "pt.value". Otherwise, the data setup is similar to your own. Note that df$year will be set as numeric, so it's best to change that into either Date format (kinda more trouble than it's worth here), or just as a factor, since "2017.5" isn't gonna make too much sense here :). The point is, I need "year" to be discrete, not continuous.

    Solve the color error

    For the plot, I'll try to create it similar to you. Here note that in the scale_fill_manual object, you have to set the values= argument using a list. In your example code, you are using a vector (c()) to specify the colors and naming. If you have name1=color1, name2=color2,..., this represents a list structure.

    ggplot(df, aes(x=as.factor(year), y=values)) + 
        geom_col(aes(fill=species), position=position_dodge(width=0.62), width=0.6) + 
        scale_fill_manual(values=
            list('ew' = 'skyblue1', 'things' = 'dodgerblue',
                'things1'='midnightblue', 'wee beasties' = 'gray')) +
        geom_point(aes(y=pt.value), shape=24, position=position_dodge(width=0.62)) +
        theme_bw() + labs(x='Year')
    

    enter image description here

    So the colors are applied correctly and my axis is discrete, and the y values of the points are mapped to pt.value like I wanted, but why don't the points dodge?!

    Solve the dodging issue

    Dodging is a funny thing in ggplot2. The best reasoning here I can give you is that for columns and barplots, dodging is sort of "built-in" to the geom, since the default position is "stack" and "dodge" represents an alternative method to draw the geom. For points, text, labels, and others, the default position is "identity" and you have to be more explicit in how they are going to dodge or they just don't dodge at all.

    Basically, we need to let the points know what they are dodging based on. Is it "species"? With geom_col, it's assumed to be, but with geom_point, you need to specify. We do that by using a group= aesthetic, which let's the geom_point know what to use as criteria for dodging. When you add that, it works!

    ggplot(df, aes(x=as.factor(year), y=values, group=species)) + 
        geom_col(aes(fill=species), position=position_dodge(width=0.62), width=0.6) + 
        scale_fill_manual(values=
            list('ew' = 'skyblue1', 'things' = 'dodgerblue',
                'things1'='midnightblue', 'wee beasties' = 'gray')) +
        geom_point(aes(y=pt.value), shape=24, position=position_dodge(width=0.62)) +
        theme_bw() + labs(x='Year')
    

    enter image description here