如何在ggplot中控制Facet_wrap中的垂直空间
How to control vertical spaces in Facet_wrap in ggplot
我创建了一个跨评级和地理两个维度的分面图 (Geo_class)。如何在不同地理 classes (panel.spacing.x) 之间引入 space,同时避免在评级 classes 之间引入 space。此处示例数据 https://www.dropbox.com/s/n3tbiexbvpuqm3t/Final_impact_melt_All5.csv?dl=0
下图中1到3、4、5、6、7代表Ratings,Geo_Class是(Saudi Arabia, NOn GCC, Other GCC and All)。方法是新的还是旧的。
我使用以下代码生成图
p<-ggplot(Final_impact_melt_All5, aes(x=Method, y=Capital_Charge, fill= Capital_Charge_type))+ geom_bar(stat='Identity', width= 1)
p + facet_wrap (Geo_class ~ Ratings, nrow = 2) + scale_fill_brewer(palette ="Oranges") + theme(axis.text=element_text(size=6),panel.spacing.x=unit(0, "lines"),panel.spacing.y=unit(1, "lines"))
我喜欢的是将图表分成 4 个面板(Geo_class 每个面板一个,即沙特阿拉伯、其他海湾合作委员会、非海湾合作委员会和所有)。我想将评级之间的间距保持为零,这样就呈现出集群堆叠条形图的外观。
另一个好处是,如果我可以多次摆脱地理 class 的重复,它只在 4 个新面板的每个面板上显示一次。
这是你想要的吗?据我所知,仅使用 ggplot
无法完成您的要求。下面的代码并不漂亮。这取决于 gtable
和 grid
函数。它分解 ggplot 图中的条带,然后以适当的间距构造新的条带。该代码适用于示例中内部和外部条带标签的特定配置。如果发生变化,代码就会中断。它可能无法在下一个版本的 ggplot 中存活下来。
library(ggplot2)
library(grid)
library(gtable)
# Set spacing between Geo_class and between Ratings
OuterSpacing = unit(5, "pt") # spacing between Geo_class
InnerSpacing = unit(0, "pt") # spacing between Ratings
# Your ggplot
p <- ggplot(Final_impact_melt_All5,
aes(x=Method, y=Capital_Charge, fill= Capital_Charge_type)) +
geom_bar(stat='Identity', width= 1)
plot = p +
facet_wrap (Geo_class ~ Ratings, nrow = 2) +
scale_fill_brewer(palette ="Oranges") +
theme(axis.text=element_text(size=6),
panel.spacing.x = OuterSpacing,
panel.spacing.y = unit(1, "lines"))
# Get the ggplot grob
g = ggplotGrob(plot)
# Set spacing between 'Ratings' to 'InnerSpacing'
g$widths[c(seq(6, by=4, length.out=4), seq(26, by=4, length.out=4)) ] = InnerSpacing
# Get a list of strips
strip = lapply(grep("strip-t", g$layout$name), function(x) {g$grobs[[x]]})
# Number of strips
URow = 4; LRow = 5 # Top row and Bottom row
# Construct gtable to contain the new strip
Inner = (rep(unit.c(unit(1, "null"), InnerSpacing), LRow))[-10]
newStrip = gtable(widths = (rep(unit.c(Inner, OuterSpacing), URow))[-40],
heights = strip[[1]]$heights)
## Populate the gtable
# Top Row
cols1 = seq(1, by = 5, length.out = 4)
cols2 = (seq(1, by = 10, length.out = 4))
newStrip = gtable_add_grob(newStrip, lapply(strip[cols1], `[`, 1), t = 1, l = cols2, r = cols2 + 8)
# Bottom row
cols = seq(1, by = 2, length.out = 20)
newStrip = gtable_add_grob(newStrip, lapply(strip, `[`, 2), t = 2, l = cols)
## Add the strips to the plot,
# making sure the second half go in the upper section (t=6)
# and the first half go in the lower section (t=11)
pgNew = gtable_add_grob(g, newStrip[1:2, 21:39], t = 6, l = 4, r = 40)
pgNew = gtable_add_grob(pgNew, newStrip[1:2, 1:19], t = 11, l = 4, r = 40)
# Remove the original strip
for(i in 102:121) pgNew$grobs[[i]] = nullGrob()
# Draw the plot
grid.newpage()
grid.draw(pgNew)
我创建了一个跨评级和地理两个维度的分面图 (Geo_class)。如何在不同地理 classes (panel.spacing.x) 之间引入 space,同时避免在评级 classes 之间引入 space。此处示例数据 https://www.dropbox.com/s/n3tbiexbvpuqm3t/Final_impact_melt_All5.csv?dl=0
下图中1到3、4、5、6、7代表Ratings,Geo_Class是(Saudi Arabia, NOn GCC, Other GCC and All)。方法是新的还是旧的。
p<-ggplot(Final_impact_melt_All5, aes(x=Method, y=Capital_Charge, fill= Capital_Charge_type))+ geom_bar(stat='Identity', width= 1)
p + facet_wrap (Geo_class ~ Ratings, nrow = 2) + scale_fill_brewer(palette ="Oranges") + theme(axis.text=element_text(size=6),panel.spacing.x=unit(0, "lines"),panel.spacing.y=unit(1, "lines"))
我喜欢的是将图表分成 4 个面板(Geo_class 每个面板一个,即沙特阿拉伯、其他海湾合作委员会、非海湾合作委员会和所有)。我想将评级之间的间距保持为零,这样就呈现出集群堆叠条形图的外观。
另一个好处是,如果我可以多次摆脱地理 class 的重复,它只在 4 个新面板的每个面板上显示一次。
这是你想要的吗?据我所知,仅使用 ggplot
无法完成您的要求。下面的代码并不漂亮。这取决于 gtable
和 grid
函数。它分解 ggplot 图中的条带,然后以适当的间距构造新的条带。该代码适用于示例中内部和外部条带标签的特定配置。如果发生变化,代码就会中断。它可能无法在下一个版本的 ggplot 中存活下来。
library(ggplot2)
library(grid)
library(gtable)
# Set spacing between Geo_class and between Ratings
OuterSpacing = unit(5, "pt") # spacing between Geo_class
InnerSpacing = unit(0, "pt") # spacing between Ratings
# Your ggplot
p <- ggplot(Final_impact_melt_All5,
aes(x=Method, y=Capital_Charge, fill= Capital_Charge_type)) +
geom_bar(stat='Identity', width= 1)
plot = p +
facet_wrap (Geo_class ~ Ratings, nrow = 2) +
scale_fill_brewer(palette ="Oranges") +
theme(axis.text=element_text(size=6),
panel.spacing.x = OuterSpacing,
panel.spacing.y = unit(1, "lines"))
# Get the ggplot grob
g = ggplotGrob(plot)
# Set spacing between 'Ratings' to 'InnerSpacing'
g$widths[c(seq(6, by=4, length.out=4), seq(26, by=4, length.out=4)) ] = InnerSpacing
# Get a list of strips
strip = lapply(grep("strip-t", g$layout$name), function(x) {g$grobs[[x]]})
# Number of strips
URow = 4; LRow = 5 # Top row and Bottom row
# Construct gtable to contain the new strip
Inner = (rep(unit.c(unit(1, "null"), InnerSpacing), LRow))[-10]
newStrip = gtable(widths = (rep(unit.c(Inner, OuterSpacing), URow))[-40],
heights = strip[[1]]$heights)
## Populate the gtable
# Top Row
cols1 = seq(1, by = 5, length.out = 4)
cols2 = (seq(1, by = 10, length.out = 4))
newStrip = gtable_add_grob(newStrip, lapply(strip[cols1], `[`, 1), t = 1, l = cols2, r = cols2 + 8)
# Bottom row
cols = seq(1, by = 2, length.out = 20)
newStrip = gtable_add_grob(newStrip, lapply(strip, `[`, 2), t = 2, l = cols)
## Add the strips to the plot,
# making sure the second half go in the upper section (t=6)
# and the first half go in the lower section (t=11)
pgNew = gtable_add_grob(g, newStrip[1:2, 21:39], t = 6, l = 4, r = 40)
pgNew = gtable_add_grob(pgNew, newStrip[1:2, 1:19], t = 11, l = 4, r = 40)
# Remove the original strip
for(i in 102:121) pgNew$grobs[[i]] = nullGrob()
# Draw the plot
grid.newpage()
grid.draw(pgNew)