【问题标题】:Positioning x-axis text/label along x-axis based on another field in the data using ggplot使用ggplot根据数据中的另一个字段沿x轴定位x轴文本/标签
【发布时间】:2018-07-17 07:11:48
【问题描述】:

我想根据另一个字段放置每个 x 轴文本/标签。 ggplot2 中是否有本地方式来实现这一点?目前我正在通过geom_text 进行操作。这是我的数据和情节。这种方法有两个问题-

  1. 标签落在绘图区域内
  2. 对于一个方面,标签应该只出现在最底部的子图中,如下所示

并非在所有子图中都如下所示(我的图)。 (上图取自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)

我想根据dist 放置Tag 标签。

【问题讨论】:

  • 我不清楚问题是什么。 “它看起来不那么整洁”太模糊了,无法得到直接的答案。
  • 我现在把问题说清楚了

标签: r ggplot2


【解决方案1】:

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

第一个使用annotation_custom 的版本。默认annotation_custom 在所有面板中绘制注释。但稍作改动(取自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))

# 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)

第二个绘制两个图表: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, 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_params[[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)

【讨论】:

    【解决方案2】:

    我尝试自己解决问题,但遇到了一些问题。我在 SO here 上发布了另一个问题。答案和问题一起在一定程度上解决了这个问题。这是一个可能的解决方案。

    p <- 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_label(data  = mydata %>% dplyr::filter(PNo %in% c('X-3','X-4')),aes(x = dist,y=0,label = Tag),size=6,inherit.aes=F,color = 'red') 
    library(grid) 
    gt <- ggplot_gtable(ggplot_build(p)) 
    gt$layout$clip[grep("panel-2-\\d+", gt$layout$name)] <- "off"
    grid.draw(gt) 
    

    【讨论】:

      猜你喜欢
      • 2018-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多