Manually changing linetype order and offsetting er

2020-04-12 16:42发布

问题:

Using these data

Data <- structure(list(value = c(180, 528, 180, 147, 468, 151, 194, 568, 
210), SE = c(21.7869586486209, 21.0831764730322, 21.2726560659361, 
21.7869586486209, 21.0831764730322, 21.2726560659361, 21.7869586486209, 
21.0831764730322, 21.2726560659361), PredictionType = c("InSitu", 
"ExSitu", "ExSitu", "ExSitu", "InSitu", "ExSitu", "ExSitu", "ExSitu", 
"InSitu"), Area = c("AAA", "BBB", "CCC", "AAA", "BBB", "CCC", 
"AAA", "BBB", "CCC")), .Names = c("value", "SE", "PredictionType", 
"Area"), class = "data.frame", row.names = c(NA, -9L))

and the following code I can produce the plot below.

ggplot(Data)+
  geom_point(aes(x=Area, y=value, color=Area),size=3, shape=1)+
  geom_errorbar(aes(x=Area, ymin=value-SE, ymax=value+SE, color=Area, linetype = PredictionType),cex=0.75)

The linetype is correctly distinguishing between ExSitu and InSitu predictions, but I want the line type to be reversed. Equivocally, i want the dotted line to be ExSitu and the solid line to be InSitu.

Also, is it possible to offset the error bars so that they are not directly on top of each other? Ideally I would want the solid InSitu estimate centered over the area (AAA, BBB, CCC) and the two dotted ExSitu estimates slightly right and left of center.

Thanks in advance.

回答1:

You can use position argument to offset (dodge) points and error bars (see e.g. here). However, you have more than one point/error bar with the same 'PredictionType' within each 'Area', and need to create a new variable with a unique value for each point within Area to make the dodge-ing work. Here I use ave to create the dummy variable. I 'borrow' an unused aesthetics, fill, for the dodging, and then remove the fill legend. The order in which the linetypes are used is changed in scale_linetype_manual.

Data$id <- with(Data, ave(Area, Area, FUN = seq_along))
dodge <- position_dodge(width = 0.4)

ggplot(Data, aes(x = Area, y = value, fill = id, colour = Area, linetype = PredictionType)) +
  geom_point(size = 3, shape = 1, position = dodge) +
  geom_errorbar(aes(ymin = value - SE, ymax = value + SE),
                cex = 0.75, position = dodge) +
  scale_linetype_manual(values = c("dotted", "solid")) +
  scale_fill_discrete(guide = FALSE) 

Update following comment:

In order to place the 'InSitu' points in the middle, one possibility is to set the id variable to 2 for 'InSitu' data, and to 1 and 3 respectively for 'ExSitu' data:

Data <- Data[order(Data$Area, Data$PredictionType), ]
Data$id <- as.character(c(1, 3, 2))

ggplot(Data, aes(x = Area, y = value, fill = id, colour = Area, linetype = PredictionType)) +
  geom_point(size = 3, shape = 1, position = dodge) +
  geom_errorbar(aes(ymin = value - SE, ymax = value + SE),
                size = 1, width = 0.5, position = dodge) +
  scale_linetype_manual(values = c("dotted", "solid")) +
  scale_fill_discrete(guide = FALSE)



回答2:

ggplot coerces PredictionType to a factor, and then assigns each level of the factor to a linetype, in the order that the levels occur. The default puts ExSitu first, so you can fix that in a couple ways.

First, you can convert PredictionType to a factor yourself, and assign the levels you want directly:

Data$PredictionType = factor(Data$PredictionType,levels=c('InSitu','ExSitu'))

Or, you can just call convert it right when you give it to ggplot (although you might need to change the legend title):

ggplot(Data)+
geom_point(aes(x=Area, y=value, color=Area),size=3, shape=1)+
geom_errorbar(aes(x=Area, ymin=value-SE, ymax=value+SE, color=Area, linetype = factor(PredictionType,levels=c('InSitu','ExSitu'))),cex=0.75)


标签: r ggplot2