Add secondary X axis labels to ggplot with one X axis

筅森魡賤 提交于 2019-11-28 01:31:39
Axeman

Something like this, perhaps. Note the setting of expand for both axes to deal with proper spacing, and positions of the category names.

The labels in your figure aren't really off-centre, they are in the centre of their category boundary. It's just that by default the axes are expanded a bit further.

If you want to get more fancy, you can draw outside of the plotting area too, but it requires a bit more fiddeling. This question should get you started.

ggplot(mpg, aes(class))+
  geom_bar()+
  geom_text(data = data.frame(br = breaks.minor), aes(y = br, label = br, x = 7.75),
            size = 4, col = 'grey30') +
  coord_flip()+
  scale_y_continuous(limit = lims, minor_breaks = breaks.minor, 
                     breaks = breaks.major, labels = labels.minor, 
                     expand = c(0, 0)) +
  scale_x_discrete(expand = c(0.05, 0)) +
  theme(panel.grid.major.x = element_blank()) +
  theme(panel.grid.major.y = element_blank()) +
  theme(axis.ticks.x=element_blank()) +
  theme(axis.title= element_blank())

I think this does what you're looking for:

library(ggplot2)
library(grid)
library(gtable)
library(gridExtra)

breaks.major <- c(0, 15, 37.5, 52.5, 67.5, 82.5, 95, 100)
breaks.minor <- c(30, 45, 60, 75, 90)
labels.minor <- c("", "Extremely\nDissatisfied", "Dissatisfied", "Uncertain",
                  "Satisfied", "Very\nSatisfied", "Extremely\nSatisfied", "")
lims <- c(0, 100)

# build the main plot with the text axis
gg1 <- ggplot(mpg, aes(class))
gg1 <- gg1 + geom_bar()
gg1 <- gg1 + scale_y_continuous(expand=c(0,0), limit=lims, 
                                minor_breaks=breaks.minor, 
                                breaks=breaks.major,
                                labels=labels.minor)
gg1 <- gg1 + coord_flip()
gg1 <- gg1 + theme(panel.grid.major.x=element_blank())
gg1 <- gg1 + theme(panel.grid.major.y=element_blank())
gg1 <- gg1 + theme(axis.ticks.x=element_blank())
gg1 <- gg1 + theme(axis.title=element_blank())

# let ggplot2 do the work of building the second axis
gg2 <- ggplot(mpg, aes(class))
gg2 <- gg2 + scale_y_continuous(expand=c(0,0), limit=lims, 
                                breaks=c(0, breaks.minor, 100))
gg2 <- gg2 + coord_flip()
gg2 <- gg2 + theme(axis.ticks.x=element_blank())
gg2 <- gg2 + theme(axis.text.x=element_text(hjust=c(0, 0.5, 0.5, 0.5, 0.5, 0.5, 1)))

gt1 <- ggplot_gtable(ggplot_build(gg1))
gt2 <- ggplot_gtable(ggplot_build(gg2))
axis2 <- grid.arrange(gt2$grobs[[5]])

gt <- gtable_add_rows(gt1, unit(0.1, "null"), 4)
grid.arrange(gtable_add_grob(gt, axis2, t=5, l=4, b=5, r=4))

I wrote all labels as major-labels.

# OP's
breaks.major <- c(0,15,37.5,52.5,67.5,82.5,95,100) #defines the midpoints of the categories (label locations)
breaks.minor <- c(30,45,60,75,90) #defines the edges of the categories (second label set I need)
labels.minor <- c("","Extremely \nDissatisfied","Dissatisfied","Uncertain","Satisfied","Very \nSatisfied","Extremely \nSatisfied","")
lims =c(0,100)

breaks.major2 <- c(0,15,37.5,52.5,67.5,82.5,95)
breaks.minor2 <- c(30,45,60,75,90,100)       # put 100 into minor from major

breaks.comb <- sort(c(breaks.major2, breaks.minor2 - 1.0E-6))  # avoid the just same value as minor
label.comb <- c(0, "\nExtremely \nDissatisfied", 30, "\nDissatisfied", 45, "\nUncertain", 60, 
                "\nSatisfied", 75, "\nVery \nSatisfied", 90, "\nExtremely \nSatisfied", 100)

library(ggplot2)
g <- ggplot(mpg, aes(class))+
  geom_bar()+
  coord_flip()+
  scale_y_continuous(limit = lims, minor_breaks = breaks.minor2, breaks = breaks.comb, 
                     labels = label.comb, expand = c(0,0)) +
  theme(panel.grid.major.x = element_blank()) +
  theme(panel.grid.major.y = element_blank()) +
  theme(axis.ticks.x=element_blank()) +
  theme(axis.title= element_blank()) +
  theme(plot.margin = unit(c(0.5, 0.5, 0.5, 0.5), "lines"))

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!