Amanda Goldberg
Amanda Goldberg

Reputation: 363

ggplot2 and jitter/dodge points by a group

I have 'elevation' as my y-axis and I want it as a discrete variable (in other words I want the space between each elevation to be equal and not relative to the numerical differences). My x-axis is 'time' (julian date).

    mydata2<- data.frame(
                   "Elevation" = c(rep(c(1200),10),rep(c(1325.5),10),rep(c(1350.75),10), rep(c(1550.66),10)),
                   "Sex" = c(rep(c("F","M"),20)),
                   "Type" = c(rep(c("emerge","emerge","endhet","endhet","immerge","immerge","melt","melt", "storpor","storpor"),4)),
                   "mean" = c(rep(c(104,100,102,80,185,210,84,84,188,208,104,87,101,82, 183,188,83,83,190,189),2))
                   "se"=c(rep(c(.1,.01,.2,.02,.03),4)))

mydata2$Sex<-factor(mydata2$Sex))
mydata2$Type<-factor(mydata2$Type))
mydata2$Elevation<-factor(mydata2$Elevation))

at<-ggplot(mydata2, aes(y = mean, x = Elevation,color=Type, group=Sex)) +
  geom_pointrange(aes(ymin = mean-se, ymax = mean+se), 
                  position=position_jitter(width=0.2,height=.1), 
                  linetype='solid') +
  facet_grid(Sex~season,scales = "free")+
  coord_flip()

at

enter image description here

Ideally, I would like each 'type' to be separated vertically. When I jitter or dodge only those that are close separate and not evenly. Is there a way to force each 'type' to be slightly shifted so they are all on their own line? I tried to force it by giving each type a slightly different 'elevation' but then I end up with a messy y-axis (I can't figure out a way to keep the point but not display all the tick marks with a discrete scale).

Thank you for your help.

Upvotes: 2

Views: 1821

Answers (1)

dc37
dc37

Reputation: 16178

If you want to use a numerical value as a discrete value, you should use as.factor. In your example, try to use x = as.factor(Elevation).

Additionally, I will suggest to use position = position_dodge() to get points from different conditions corresponding to the same elevation to be plot side-by-side

ggplot(mydata2, aes(y = mean, x = as.factor(Elevation),color=Type, group=Sex)) +
  geom_pointrange(aes(ymin = mean-se, ymax = mean+se), 
                  position=position_dodge(), 
                  linetype='solid') +
  facet_grid(Sex~season,scales = "free")+
  coord_flip()

EDIT with example data provided by the OP

Using your dataset, I was not able to get range being plot with your point. So, I create two variable Lower and Upper using dplyr package.

Then, I did not pass your commdnas facotr(...) you provided in your question but instead, I used as.factor(Elevation) and position_dodge(0.9) for the plotting to get the following plot:

library(tidyverse)
mydata2 %>% mutate(Lower = mean-se*100, Upper = mean+se*100) %>%
  ggplot(., aes( x = as.factor(Elevation), y = mean, color = Type))+
  geom_pointrange(aes(ymin = Lower, ymax = Upper), linetype = "solid", position = position_dodge(0.9))+
  facet_grid(Sex~., scales = "free")+
  coord_flip()

enter image description here

Does it look what you are looking for ?

Data Your dataset provided contains few errors (too much parenthesis), so I correct here.

mydata2<- data.frame(
  "Elevation" = c(rep(c(1200),10),rep(c(1325.5),10),rep(c(1350.75),10), rep(c(1550.66),10)),
  "Sex" = rep(c("F","M"),20),
  "Type" = rep(c("emerge","emerge","endhet","endhet","immerge","immerge","melt","melt", "storpor","storpor"),4),
  "mean" = rep(c(104,100,102,80,185,210,84,84,188,208,104,87,101,82, 183,188,83,83,190,189),2),
  "se"=rep(c(.1,.1,.2,.05,.03),4))

Upvotes: 3

Related Questions