使用ggplot根据数据中的另一个字段沿x轴定位x轴文本/标签 [英] Positioning x-axis text/label along x-axis based on another field in the data using ggplot

查看:123
本文介绍了使用ggplot根据数据中的另一个字段沿x轴定位x轴文本/标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想根据其他字段放置每个x轴文本/标签。在 ggplot2 中有一种本地方式来达到这个目的?目前我正在通过 geom_text 来完成它。这里是我的数据和情节。我有两个问题,这种方法 -


  1. 标签正在落在绘图区内

  2. 对于某个方面,标签只应出现在最下面的子图中,如下所示

并非如下图所示的所有子图(我的图)。 (上图为

解决方案

我注意到您已经在其他地方接受了答案,并且你在这里回答了你自己的问题。但他们不完全回答你原来的问题。特别是,标签仍在绘图面板内。我提供了两种可能性,但都不是直截了当的。

第一种使用 annotation_custom 版本。默认 annotation_custom 会在所有面板中绘制注释。但有一个小改动(摘自



第二张绘制两张图表:p1是您的条形图,而p2仅包含标签。诀窍是让两个图表中的x轴相同。然后,绘图面板从p2中提取出来,并放置到p1中,但进入p1绘图面板下方的新行中。

  library(ggplot2)
library(magrittr)
mydata = data.frame(expand.grid( Tag = c('A','B','C'),
Year = 2010:2011,PNo = paste0(X-,1:4)),Value = round(runif(24, )
mydata $ dist = ifelse(mydata $ Tag =='A',0,ifelse(mydata $ Tag =='B',2,7))

#bar图
p1 = mydata%>%ggplot(aes(x = dist,y = Value,fill = factor(Year)))+
geom_bar(stat ='summary',position ='dodge',fun.y ='mean',width = 1)+
facet_wrap(〜PNo,ncol = 2)+
theme(axis.text.x = element_blank(),axis)。 ticks.x = element_blank())

#为了得到x值的范围 -
#,这样p1和下面p2中x轴的范围是相同的$
gd = ggplot_build(p1)
xrange = gd $ layout $ panel_ranges [[1]] $ x.range#p2中使用的xrange(见下文)

# (A,B和C)仅
p2 = mydata%>%ggplot(aes(x = dist,y = Value))+
facet_wrap (〜PNo,ncol = 2)+
geom_label(aes(x = dist,y = 0,label = Tag),size = 6,inherit.aes = F,color ='red')+
### geom_text(aes(x = dist,y = 0,label = Tag),size = 6,color ='red')+ ###标签的另一种样式
scale_x_continuous(lim = xrange,expand = c(0,0))+
theme_bw()+
theme(panel.grid = element_blank(),
panel.border = element_rect(color = NA))


#从p2中获取一个绘图面板
g2 = ggplotGrob(p2)
panels = subset(g2 $ layout,grepl(panel,g2 $ layout $ name), t:r)
panels = subset(panels,t == min(t))

g2 = g2 [unique(panels $ t),min(panels $ l):max面板$ r)]

#向p1添加一行以绘制面板
library(gtable)
library(grid)
g1 < - ggplotGrob p1)
pos = max(subset(g1 $ layout,grepl(panel,g1 $ layout $ name),t))
g1 = gtable_add_rows(g1,height = unit(2,lines ),pos = pos)

#将面板(g2)添加到新行
g1 = gta ble_add_grob(g1,g2,t = pos + 1,l = min(面板$ l),r = max(面板$ r))

#绘制图表
grid.newpage )
grid.draw(g1)

a>


I would like to place each x-axis text/label based on another field. Is there a native way in ggplot2 to achieve this? Presently I am doing it through geom_text. Here are my data and the plot.I have two issues with this approach -

  1. Labels are falling inside the plot area
  2. For a facet the labels should only appear at the bottom-most subplots as below

not in all subplots as is the case below (my plot). (The above image was taken from here)

library(ggplot2)
library(magrittr)    

mydata = data.frame(expand.grid(Tag = c('A','B','C'),
  Year = 2010:2011,PNo = paste0("X-",1:4)),Value = round(runif(24,1,20)))
mydata$dist = ifelse(mydata$Tag == 'A',0,ifelse(mydata$Tag=='B',2,7))

mydata %>% ggplot(aes(x = dist,y = Value,fill = factor(Year))) +
  geom_bar(stat='summary',position = 'dodge',fun.y='mean',width=1) +
  facet_wrap(~PNo,ncol=2) +
  theme(axis.text.x = element_blank(),axis.ticks.x = element_blank()) +
  geom_text(aes(x = dist,label = Tag),color = 'black',size=4,angle = 0,show.legend = F)

I would like to place Tag labels based on dist.

解决方案

I notice that you have accepted an answer elsewhere, and that you have answered you own question here. But they don't quite answer your original question. In particular, the labels are still inside the plot panel. I offer two possibilities, but neither being straightforward.

The first uses a version of annotation_custom. The default annotation_custom draws the annotation in all panels. But with a small alteration (taken from here), it can be made to draw annotations in selected panels - for your plot, the lower two panels.

 library(ggplot2)
library(magrittr)    
mydata = data.frame(expand.grid(Tag = c('A', 'B', 'C'), 
             Year = 2010:2011, PNo =  paste0("X-", 1:4)), Value = round(runif(24,1,20)))
mydata$dist = ifelse(mydata$Tag == 'A', 0, ifelse(mydata$Tag == 'B', 2, 7))

# The bar plot. Note extra margin above x-axis title.
# This gives space for the annotations between the panel and the title.
p1 = mydata %>% ggplot() +
  geom_bar(aes(x = dist, y = Value, fill = factor(Year)),
             width = 1, stat = 'identity', position = "dodge") + 
  facet_wrap(~PNo, ncol = 2) +
  theme(axis.text.x = element_blank(), 
        axis.ticks.x = element_blank(),
        axis.title.x = element_text(margin = margin(t = 2, unit = "lines")))   

# Baptiste's modification to annotation_custom
annotation_custom2 = 
function (grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, data) {
  layer(data = data, stat = StatIdentity, position = PositionIdentity, 
        geom = ggplot2:::GeomCustomAnn,
        inherit.aes = TRUE, params = list(grob = grob, 
                                          xmin = xmin, xmax = xmax, 
                                          ymin = ymin, ymax = ymax))
}

# The plot with annotations. (ymin and ymax set to -Inf 
# draws the annotation at the bottom of the panel. 
# vjust = 1.5 drops them below the panel). 
for (i in 1:length(unique(mydata$Tag)))  {
   p1 = p1 + annotation_custom2(
        grob =  textGrob(label = unique(mydata$Tag)[i], vjust = 1.5,
                      gp = gpar(col = 'red', cex = 1)),
         xmin = unique(mydata$dist)[i],
         xmax = unique(mydata$dist)[i],
         ymin = -Inf,
         ymax = -Inf,
         data=data.frame(PNo=c("X-3", "X-4") ))    # The two bottom panels
} 

# The annotations are placed outside the panels. 
# Therefore, have to turn off clipping to the panels.
g1 = ggplotGrob(p1)
g1$layout$clip[grepl("panel", g1$layout$name)] = "off"

# Draw the chart
grid.newpage()
grid.draw(g1)

The second draws two charts: p1 is your bar plot, and p2 contains the labels only. The trick is to get the x-axes in the two charts to be the same. Then, plot panels are extracted from p2, and placed into a p1, but into a new row just below p1's plot panel.

library(ggplot2)
library(magrittr)    
mydata = data.frame(expand.grid(Tag = c('A', 'B', 'C'),
      Year = 2010:2011,PNo = paste0("X-", 1:4)),Value = round(runif(24, 1, 20)))
mydata$dist = ifelse(mydata$Tag == 'A', 0, ifelse(mydata$Tag == 'B', 2, 7))

# The bar plot
p1 = mydata %>% ggplot(aes(x = dist, y = Value, fill = factor(Year))) +
   geom_bar(stat = 'summary', position = 'dodge',fun.y = 'mean', width = 1) +
  facet_wrap(~PNo, ncol = 2) +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank()) 

# To get the range of x values -
# so that the extent of the x-axis in p1 and in the following p2 are the same
gd = ggplot_build(p1)
xrange = gd$layout$panel_ranges[[1]]$x.range   # xrange used in p2 (see below)

# Plot with labels (A, B, and C) only
p2 = mydata %>% ggplot(aes(x = dist, y = Value)) +
     facet_wrap(~PNo, ncol = 2) +
     geom_label(aes(x = dist, y = 0, label = Tag), size = 6, inherit.aes = F, color = 'red') +
    ### geom_text(aes(x = dist, y = 0, label = Tag), size=6, color = 'red') +  ### Alternative style for labels
     scale_x_continuous(lim = xrange, expand = c(0,0)) +
     theme_bw() +
     theme(panel.grid = element_blank(),
           panel.border = element_rect(colour = NA)) 


# Grab a plot panel from p2
g2 = ggplotGrob(p2)
panels = subset(g2$layout, grepl("panel", g2$layout$name), t:r)
panels = subset(panels, t == min(t))

g2 = g2[unique(panels$t), min(panels$l):max(panels$r)]

# Add a row to p1 to take the plot panels
library(gtable)
library(grid)
g1 <- ggplotGrob(p1)
pos = max(subset(g1$layout, grepl("panel", g1$layout$name), t))
g1 = gtable_add_rows(g1, height = unit(2, "lines"), pos = pos)

# Add the panel (g2) to the new row
g1 = gtable_add_grob(g1,g2, t = pos + 1, l =  min(panels$l), r = max(panels$r))

# Draw the chart
grid.newpage()
grid.draw(g1)

这篇关于使用ggplot根据数据中的另一个字段沿x轴定位x轴文本/标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆