我想根据另一个字段放置每个x轴文本/标签。 ggplot2
中是否有本地方式来实现这一目标?目前我正在通过geom_text
进行此操作。这是我的数据和情节。这个方法有两个问题 -
不是所有的子图,如下面的情况(我的情节)。 (上图来自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)
答案 0 :(得分: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> s绘图面板下方的新行中。
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)
答案 1 :(得分:0)
我试图自己解决问题,但面临一些问题。我在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)