具有嵌套分组变量的多轴标签

paw*_*els 32 r bar-chart ggplot2 axis-labels

我希望两个不同的嵌套分组变量的级别出现在图表下方的单独行中,而不是在图例中.我现在拥有的是这段代码:

data <- read.table(text = "Group Category Value
    S1 A   73
    S2 A   57
    S1 B   7
    S2 B   23
    S1 C   51
    S2 C   87", header = TRUE)

ggplot(data = data, aes(x = Category, y = Value, fill = Group)) + 
  geom_bar(position = 'dodge') +
  geom_text(aes(label = paste(Value, "%")), 
            position = position_dodge(width = 0.9), vjust = -0.25)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我想拥有的是这样的:

在此输入图像描述

有任何想法吗?

aos*_*ith 44

ggplot2 2.2.0 以来的strip.position参数facet_wrap()switch参数现在通过分面创建这个绘图的简单版本相当简单.要为绘图提供不间断的外观,请将其设置为0.facet_grid()panel.spacing

以下是使用@ agtudy答案的每个类别的不同组数的数据集的示例.

  • 我曾经scales = "free_x"从没有它的类别中删除额外的组,尽管这并不总是可取的.
  • strip.position = "bottom"参数将构面标签移动到底部.我一起删除了条带背景strip.background,但我可以看到离开条形矩形在某些情况下会很有用.
  • 我曾经width = 1在每个类别触摸中制作条形图 - 默认情况下它们之间有空格.

我也用strip.placement,并strip.backgroundtheme获得底部的条状并取出纸带矩形.

ggplot2_2.2.0或更新版本的代码:

ggplot(data = data, aes(x = Group, y = Value, fill = Group)) + 
    geom_bar(stat = "identity", width = 1) +
    geom_text(aes(label = paste(Value, "%")), vjust = -0.25) +
    facet_wrap(~Category, strip.position = "bottom", scales = "free_x") +
    theme(panel.spacing = unit(0, "lines"), 
         strip.background = element_blank(),
         strip.placement = "outside")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

如果您希望所有条形宽度相同space= "free_x",facet_grid()则可以使用in ,而不管每个类别有多少组.请注意,这使用switch = "x"而不是strip.position.您还可能想要更改x轴的标签; 我不确定应该是什么,也许是Category而不是Group?

ggplot(data = data, aes(x = Group, y = Value, fill = Group)) + 
    geom_bar(stat = "identity", width = 1) +
    geom_text(aes(label = paste(Value, "%")), vjust = -0.25) +
    facet_grid(~Category, switch = "x", scales = "free_x", space = "free_x") +
    theme(panel.spacing = unit(0, "lines"), 
         strip.background = element_blank(),
         strip.placement = "outside") + 
    xlab("Category")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

较旧的代码版本

ggplot2_2.0.0的代码,首次引入此功能时,有点不同.为了后人,我把它保存在下面:

ggplot(data = data, aes(x = Group, y = Value, fill = Group)) + 
    geom_bar(stat = "identity") +
    geom_text(aes(label = paste(Value, "%")), vjust = -0.25) +
    facet_wrap(~Category, switch = "x", scales = "free_x") +
    theme(panel.margin = unit(0, "lines"), 
         strip.background = element_blank())
Run Code Online (Sandbox Code Playgroud)


ags*_*udy 18

您可以为其创建自定义元素功能axis.text.x.

在此输入图像描述

library(ggplot2)
library(grid)

## create some data with asymmetric fill aes to generalize solution 
data <- read.table(text = "Group Category Value
                   S1 A   73
                   S2 A   57
                   S3 A   57
                   S4 A   57
                   S1 B   7
                   S2 B   23
                   S3 B   57
                   S1 C   51
                   S2 C   57
                   S3 C   87", header=TRUE)

# user-level interface 
axis.groups = function(groups) {
  structure(
    list(groups=groups),
    ## inheritance since it should be a element_text
    class = c("element_custom","element_blank")  
  )
}
# returns a gTree with two children: 
# the categories axis
# the groups axis
element_grob.element_custom <- function(element, x,...)  {
  cat <- list(...)[[1]]
  groups <- element$group
  ll <- by(data$Group,data$Category,I)
  tt <- as.numeric(x)
  grbs <- Map(function(z,t){
    labs <- ll[[z]]
    vp = viewport(
             x = unit(t,'native'), 
             height=unit(2,'line'),
             width=unit(diff(tt)[1],'native'),
             xscale=c(0,length(labs)))
    grid.rect(vp=vp)
    textGrob(labs,x= unit(seq_along(labs)-0.5,
                                'native'),
             y=unit(2,'line'),
             vp=vp)
  },cat,tt)
  g.X <- textGrob(cat, x=x)
  gTree(children=gList(do.call(gList,grbs),g.X), cl = "custom_axis")
}

## # gTrees don't know their size 
grobHeight.custom_axis = 
  heightDetails.custom_axis = function(x, ...)
  unit(3, "lines")

## the final plot call
ggplot(data=data, aes(x=Category, y=Value, fill=Group)) + 
  geom_bar(position = position_dodge(width=0.9),stat='identity') +
  geom_text(aes(label=paste(Value, "%")),
            position=position_dodge(width=0.9), vjust=-0.25)+
  theme(axis.text.x = axis.groups(unique(data$Group)),
        legend.position="none")
Run Code Online (Sandbox Code Playgroud)


M A*_*lio 13

我知道这个问题已经很老了,但我想介绍最干净的方法来做到这一点ggh4x

library(ggplot2)
library(ggh4x)

data <- read.table(text = "Group Category Value
    S1 A   73
    S2 A   57
    S1 B   7
    S2 B   23
    S1 C   51
    S2 C   87", header = TRUE)

# Only one more line of code with the function 'guide_axis_nested'
# and changing the data from x axis to interaction(Group,Category, sep = "!")

ggplot(data = data, aes(x = interaction(Group,Category, sep = "!"), y = Value, fill = Group)) + 
  geom_col(position = 'dodge', show.legend = FALSE) +
  geom_text(aes(label = paste(Value, "%")), 
            position = position_dodge(width = 0.9), vjust = -0.25) +
  scale_x_discrete(guide = guide_axis_nested(delim = "!"), name = "Category")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


bap*_*ste 7

agstudy方法的替代方法是编辑gtable并插入由ggplot2计算的"轴",

p <- ggplot(data=data, aes(x=Category, y=Value, fill=Group)) + 
  geom_bar(position = position_dodge(width=0.9),stat='identity') +
  geom_text(aes(label=paste(Value, "%")),
            position=position_dodge(width=0.9), vjust=-0.25)

axis <- ggplot(data=data, aes(x=Category, y=Value, colour=Group)) +
  geom_text(aes(label=Group, y=0),
            position=position_dodge(width=0.9))

annotation <- gtable_filter(ggplotGrob(axis), "panel", trim=TRUE)
annotation[["grobs"]][[1]][["children"]][c(1,3)] <- NULL #only keep textGrob

library(gtable)
g <- ggplotGrob(p)
gtable_add_grobs <- gtable_add_grob # let's use this alias
g <- gtable_add_rows(g, unit(1,"line"), pos=4)
g <- gtable_add_grobs(g, annotation, t=5, b=5, l=4, r=4)
grid.newpage()
grid.draw(g)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


And*_*nCH 7

给出类似(但不相同)结果的非常简单的解决方案是使用刻面.缺点是类别标签高于而不是低于标签.

ggplot(data=data, aes(x=Group, y=Value, fill=Group)) +
  geom_bar(position = 'dodge', stat="identity") +
  geom_text(aes(label=paste(Value, "%")), position=position_dodge(width=0.9), vjust=-0.25) + 
  facet_grid(. ~ Category) + 
  theme(legend.position="none")
Run Code Online (Sandbox Code Playgroud)

使用刻面提供辅助标签