2015-04-23 50 views
12

你能帮我注释一个ggplot2散点图吗?用额外的勾号和标签标注ggplot

为了将典型的散点图(黑色):

df <- data.frame(x=seq(1:100), y=sort(rexp(100, 2), decreasing = T)) 
ggplot(df, aes(x=x, y=y)) + geom_point() 

我想在一个额外的滴答声的形式和自定义标签(红色)添加注释:

示例图片:

enter image description here

+0

请参阅'scale_x_continuous' –

+0

因此,我可以使用'scale_x_continuous'来更改所有刻度的格式和位置,但是我可以使用它来添加一个自定义刻度+标签吗?我没有看到。 – magum

回答

14

四种解决方案。

第一次使用scale_x_continuous添加附加元素,然后使用theme来定制新的文本和刻度标记(加上一些额外的调整)。

第二个使用annotate_custom创建新的grobs:文本grob和一行grob。 grobs的位置在数据坐标中。结果是如果y轴的极限改变,grob的定位将会改变。因此,下面的示例中y轴是固定的。另外,annotation_custom正试图在绘图面板外绘制。默认情况下,打开绘图面板的剪辑。它需要被关闭。

第三个是第二个变体(并且从here引用代码)。 grobs的默认坐标系统是'npc',因此在建造grobs时垂直放置grobs。使用annotation_custom的grobs定位使用数据坐标,因此请在annotation_custom中水平放置grobs。因此,与第二种解决方案不同,在此解决方案中Grobs的定位与y值的范围无关。

第四个使用viewports。它为查找文本和刻度标记设置了更便利的单位系统。在x方向上,位置使用数据坐标;在y方向上,位置使用“npc”坐标。因此,在这个解决方案中,grobs的定位与y值的范围无关。

首个解决方案

## scale_x_continuous then adjust colour for additional element 
## in the x-axis text and ticks 
library(ggplot2) 
df <- data.frame(x=seq(1:100), y=sort(rexp(100, 2), decreasing = T)) 

p = ggplot(df, aes(x=x, y=y)) + geom_point() + 
    scale_x_continuous(breaks = c(0,25,30,50,75,100), labels = c("0","25","xyz","50","75","100")) + 
    theme(axis.text.x = element_text(color = c("black", "black", "red", "black", "black", "black")), 
     axis.ticks.x = element_line(color = c("black", "black", "red", "black", "black", "black"), 
          size = c(.5,.5,1,.5,.5,.5))) 

# y-axis to match x-axis 
p = p + theme(axis.text.y = element_text(color = "black"), 
     axis.ticks.y = element_line(color = "black")) 

# Remove the extra grid line 
p = p + theme(panel.grid.minor = element_blank(), 
       panel.grid.major.x = element_line(color = c("white", "white", NA, "white", "white", "white"))) 
p 

enter image description here

第二种解决

## annotation_custom then turn off clipping 
library(ggplot2) 
library(grid) 
df <- data.frame(x=seq(1:100), y=sort(rexp(100, 2), decreasing = T)) 

p = ggplot(df, aes(x=x, y=y)) + geom_point() + 
scale_y_continuous(limits = c(0, 4)) + 
annotation_custom(textGrob("xyz", gp = gpar(col = "red")), 
     xmin=30, xmax=30,ymin=-.4, ymax=-.4) + 
annotation_custom(segmentsGrob(gp = gpar(col = "red", lwd = 2)), 
     xmin=30, xmax=30,ymin=-.25, ymax=-.15) 

g = ggplotGrob(p) 
g$layout$clip[g$layout$name=="panel"] <- "off" 
grid.draw(g) 

enter image description here

方案三

library(ggplot2) 
library(grid) 
df <- data.frame(x=seq(1:100), y=sort(rexp(100, 2), decreasing = T)) 

p = ggplot(df, aes(x=x, y=y)) + geom_point() 

gtext = textGrob("xyz", y = -.05, gp = gpar(col = "red")) 
gline = linesGrob(y = c(-.02, .02), gp = gpar(col = "red", lwd = 2)) 

p = p + annotation_custom(gtext, xmin=30, xmax=30, ymin=-Inf, ymax=Inf) + 
     annotation_custom(gline, xmin=30, xmax=30, ymin=-Inf, ymax=Inf) 

g = ggplotGrob(p) 
g$layout$clip[g$layout$name=="panel"] <- "off" 
grid.draw(g) 

enter image description here

方案四

更新至V2.2.0 GGPLOT2

## Viewports 
library(ggplot2) 
library(grid) 
df <- data.frame(x=seq(1:100), y=sort(rexp(100, 2), decreasing = T)) 

(p = ggplot(df, aes(x=x, y=y)) + geom_point()) 


# Search for the plot panel using regular expressions 
Tree = as.character(current.vpTree()) 
pos = gregexpr("\\[panel.*?\\]", Tree) 
match = unlist(regmatches(Tree, pos)) 
match = gsub("^\\[(panel.*?)\\]$", "\\1", match) # remove square brackets 
downViewport(match) 

####### 
# Or find the plot panel yourself 
# current.vpTree() # Find the plot panel 
# downViewport("panel.6-4-6-4") 
##### 

# Get the limits of the ggplot's x-scale, including the expansion. 
x.axis.limits = ggplot_build(p)$layout$panel_ranges[[1]][["x.range"]] 

# Set up units in the plot panel so that the x-axis units are, in effect, "native", 
# but y-axis units are, in effect, "npc". 
pushViewport(dataViewport(yscale = c(0, 1), xscale = x.axis.limits, clip = "off")) 
grid.text("xyz", x = 30, y = -.05, just = "center", gp = gpar(col = "red"), default.units = "native") 
grid.lines(x = 30, y = c(.02, -.02), gp = gpar(col = "red", lwd = 2), default.units = "native") 

upViewport(0) 

enter image description here

+1

很好的答案,没有什么补充。 – tonytonov

+1

非常感谢,我会选2号门;) – magum

0

以下将为您提供xyz标签及其上方的一行,您可能需要玩弄x和y位置以获取它们正是你想要的地方。

ggplot(df, aes(x=x, y=y)) + geom_point() + annotate(x=27, y=0, label="xyz", color="red") +annotate(x=27, ymin=-1, ymax=1, color="red") 

更多信息here如果需要。

+0

'annotate'只允许在剧情内添加注释。这不是我正在寻找的。 – magum