分面图的不同比例:scale_y_continuous()

4
我正在尝试创建一个人口金字塔,跨越多个地区。问题是这些地区的人口规模非常不同,导致y轴上的比例尺存在问题(坐标翻转)。我试图按照此处描述的方法进行操作:https://rpubs.com/walkerke/pyramids_ggplot2 - 通过使用负数表示一种性别来制作金字塔,然后使用scale_y_continuous()来消除负数。首先,我为两个国家的两个年龄组创建了一个简单的样本数据集:
country <- c(1, 1, 1, 1, 2, 2, 2, 2)
age.range <- c("0-4", "0-4", "5-9", "5-9", "0-4", "0-4", "5-9", "5-9")
sex <- rep(c("M", "F"), times = 4)
pop <- c(-8, 9, -9, 8, -88, 99, -99, 88)
pop.pyr <- data.frame(country, age.range, sex, pop)

pop.pyr

  country age.range sex pop
1       1       0-4   M  -8
2       1       0-4   F   9
3       1       5-9   M  -9
4       1       5-9   F   8
5       2       0-4   M -88
6       2       0-4   F  99
7       2       5-9   M -99
8       2       5-9   F  88

我可以建立人口金字塔,并按国家进行分面展示:
library(ggplot2)

ggplot(pop.pyr, aes(x = age.range, y = pop, fill = sex)) + 
  geom_col(data = subset(pop.pyr, sex == "M")) +
  geom_col(data = subset(pop.pyr, sex == "F")) +
  coord_flip() +
  facet_wrap(~ country, scales = "free_x")

enter image description here

为了修复y轴上的负数(coord_flip()),我需要使用:scale_y_continuous();但这样做意味着我必须为两个部分选择一个scale_y_continuous(),这是不可行的。
ggplot(pop.pyr, aes(x = age.range, y = pop, fill = sex)) + 
  geom_col(data = subset(pop.pyr, sex == "M")) +
  geom_col(data = subset(pop.pyr, sex == "F")) +
  coord_flip() +
  facet_wrap(~ country, scales = "free_x") +
  scale_y_continuous(breaks = seq(-100, 100, 20), labels = abs(seq(-100, 100, 20)))

enter image description here

唯一的解决方法是在seq中使用小变量“by”,例如scale_y_continuous(breaks = seq(-100, 100, 2), labels = abs(seq(-100, 100, 2)))。然而,这样做会使更大的尺度变得混乱。
是否有一种方法可以设置scale_y_continuous(),以便我可以在不同的facet中具有不同的刻度,同时保持:scales = free_x。否则,是否有其他方法可以使用除scale_y_continuous()之外的其他方法消除金字塔中的负数。
如果不能,那么唯一的方法就是分别开发每个图像,然后使用ggarrange()或cowplot()手动分面?
编辑:
根据评论,我尝试使用facetscales(),但我无法让它按照我想要的方式工作,也无法完全理解man文件。
使用此处的指令:https://github.com/zeehio/facetscales,我安装并加载了该软件包。
library(facetscales)

然后我创建了刻度列表:
scales.pyr <- list(`1` = scale_y_continuous(breaks = seq(-10, 10, 2), labels = abs(seq(-10, 10, 2))), `2` = scale_y_continuous(breaks = seq(-100, 100, 20), labels = abs(seq(-100, 100, 20))))

更新 ggplot:

ggplot(pop.pyr, aes(x = age.range, y = pop, fill = sex)) + 
  geom_col(data = subset(pop.pyr, sex == "M")) +
  geom_col(data = subset(pop.pyr, sex == "F")) +
  coord_flip() +
  facet_grid_sc(rows= vars(country), scales = list(y = scales.pyr))

enter image description here

这显然是不对的。man文件(https://github.com/zeehio/facetscales/blob/master/man/facet_grid_sc.Rd)中说我可以使用cols:

facet_grid_sc(rows = NULL, cols = NULL, scales = "fixed", space = "fixed", shrink = TRUE, labeller = "label_value", as.table = TRUE, switch = NULL, drop = TRUE, margins = FALSE, facets = NULL)
...
\item{cols}{一组由\code{\link[=vars]{vars()}}引用的变量或表达式,定义了行或列维度上的分面组。这些变量可以被命名(名称将传递给\code{labeller})。

如果我尝试使用cols:
ggplot(pop.pyr, aes(x = age.range, y = pop, fill = sex)) + 
geom_col(data = subset(pop.pyr, sex == "M")) +
geom_col(data = subset(pop.pyr, sex == "F")) +
coord_flip() +
facet_grid_sc(cols= vars(country), scales = list(y = scales.pyr))

我得到:

Error in .subset2(x, i, exact = exact) : 
  attempt to select less than one element in get1index

正如清楚所示,比例尺是固定的,而且man页面也说我可以使用scales = "free"或过时的"free_x"\item{scales}{由两个元素(xy)组成的列表。每个元素都可以是"fixed"(在不同facets之间共享比例尺限制)、"free"(每个facet有不同的限制) 或者一个命名列表,为每个facet值提供不同的比例尺。先前的比例尺值("fixed","free_x","free_y","free")被接受但已弃用。 但是代码示例要求用比例尺列表来填充scales参数。
最后,我真的希望在两行三列中有六个区域。man页面表明我可以使用rows和cols来分面不同的变量,但是我没有看到任何关于单个变量的nrow()ncol()的引用。在更大的例子中使用它们会出现:unused argument (ncol = 3)

请查看 facetscales 包:https://github.com/zeehio/facetscales - markus
3
可能是如何为不同的面板设置不同的比例限制?的重复问题。 - markus
scale_y_continuous(labels = abs) 对你起作用了吗?这样的话,你不必明确指定中断点。 - Z.Lin
此外,您不需要使用两个带有子集数据源的 geom_col 层。您引用的链接是指向 这个解决方案,其中将转换为负数的操作在第二个 geom 层中完成。由于您的数据已经是负数,将其拆分成两个层没有额外的好处。 - Z.Lin
谢谢@Z.Lin,它有效:scale_y_continuous(labels = abs)解决了问题。另外,你是对的,不需要两个geom_col()调用。下面提供了解决方案。 - MorrisseyJ
2个回答

2
答案很简单:使用 scale_y_continuous(labels = abs)。最终的代码如下所示:
country <- c(1, 1, 1, 1, 2, 2, 2, 2)
age.range <- c("0-4", "0-4", "5-9", "5-9", "0-4", "0-4", "5-9", "5-9")
sex <- rep(c("M", "F"), times = 4)
pop <- c(-8, 9, -9, 8, -88, 99, -99, 88)
pop.pyr <- data.frame(country, age.range, sex, pop)

library(ggplot2)

ggplot(pop.pyr, aes(x = age.range, y = pop, fill = sex)) + 
geom_col() +
coord_flip() +
scale_y_continuous(labels = abs)
facet_wrap(~ country, scales = "free_x")

在此输入图片描述

走了一大圈路,感谢@Z.Lin。


1

请提供一个使用它的示例! - socialscientist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接