Manually changing linetype order and offsetting er

2020-04-12 16:39发布

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)

enter image description here

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.

标签: r ggplot2
2条回答
姐就是有狂的资本
2楼-- · 2020-04-12 16:53

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) 

enter image description here

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)

enter image description here

查看更多
淡お忘
3楼-- · 2020-04-12 16:59

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)
查看更多
登录 后发表回答