ggplot2中两个数据集带有不同刻度的双Y轴

3
我有两个数据集(可以合并为一个),它们共享相同的 x 值,而 y 值不同 - 我想在一个数据集中绘制 y 值,并将 y 轴放在图表的左侧,同时在另一个数据集中绘制 y 值,并将 y 轴放在同一图表的右侧。当然,两个 y 轴值的相对比例是不同的(实际上应该根据第一个数据集中的 y 值进行“调整”)。两个数据集中的点将以不同的颜色区分这两个比例尺。
下面是一个示例:
d1 = data.frame(x=c(100, 200, 300, 400), y=seq(0.1, 0.4, by=0.1)) # 1st dataset
d2 = data.frame(x=c(100, 200, 300, 400), y=seq(0.8, 0.5, by=-0.1)) # 2nd dataset
p1 = ggplot(data = d1, aes(x=x, y=y)) + geom_point()
p2 = ggplot(data = d2, aes(x=x, y=y)) + geom_point() +
  scale_y_continuous(position = "right")
p1
p2

在 `ggplot2` 中,我不能执行 `p1+p2`,因为它会显示错误信息 `Error: Don't know how to add o to a plot`。请帮忙解决。谢谢!

enter image description here

1个回答

11

这种类型的图表是为什么花费了很长时间才把第二个轴引入到ggplot2中的一个很好的例子:它非常容易使人混淆,导致误解。因此,在这里我会多次提供指示物以解释每个元素的含义。

首先,使用sec_axis需要对原始轴进行转换。通常采用拦截/斜率公式进行转换,例如〜2 *。+ 10 ,其中小数点表示所需缩放的值。在这种情况下,我认为我们可以只使用〜2 *。

但是,这意味着您需要在原始轴上绘制所有数据,这意味着您需要将d2 $ y预先缩放到d1 $ y的限制。很简单,您只需要进行与sec_axis中将要使用的反向转换相同的转换。

为了使用 ggplot2 的分组功能,我将把数据组合成一个单独的 data.frame

d1 = data.frame(x=c(100, 200, 300, 400), y=seq(0.1, 0.4, by=0.1)) # 1st dataset
d2 = data.frame(x=c(100, 200, 300, 400), y=seq(0.8, 0.5, by=-0.1)) # 2nd dataset
d1$z <- "data1"
d2$z <- "data2"
d3 <- within(d2, { y = y/2 })
d4 <- rbind(d1, d3)
d4
#     x    y     z
# 1 100 0.10 data1
# 2 200 0.20 data1
# 3 300 0.30 data1
# 4 400 0.40 data1
# 5 100 0.40 data2
# 6 200 0.35 data2
# 7 300 0.30 data2
# 8 400 0.25 data2

为了控制所有组件的颜色,我将手动进行设置:

mycolors <- c("data1"="blue", "data2"="red")

最后,剧情:

library(ggplot2)
ggplot(d4, aes(x=x, y=y, group=z, color=z)) +
  geom_path() +
  geom_point() +
  scale_y_continuous(name="data1", sec.axis = sec_axis(~ 2*., name="data2")) +
  scale_color_manual(name="z", values = mycolors) +
  theme(
    axis.title.y = element_text(color = mycolors["data1"]),
    axis.text.y = element_text(color = mycolors["data1"]),
    axis.title.y.right = element_text(color = mycolors["data2"]),
    axis.text.y.right = element_text(color = mycolors["data2"])
  )

带有两个轴的示例图形

坦白地说,我不喜欢不同的斜率。也就是说,在蓝色轴上的两个方块是0.1,在红色轴上它们是0.2。如果你谈论的是两个截然不同的“事物”,那么这可能没问题。但是,如果两条线的斜率是可以直接比较的,那么你可能更喜欢保持每个方块的大小相同。为此,我们将使用仅拦截而没有斜率变化的转换。y = y - 0.4 是in-data.frame 转换,而 ~ . + 0.4 则是绘图补充,产生以下结果:

另一个带有两个轴的样本图形

PS:灵感来自于https://dev59.com/oFcO5IYBdhLWcg3whR7M#45683665https://dev59.com/FWw05IYBdhLWcg3w9mhW#6920045


2
这实际上是一个很好的例子,说明为什么双轴图会如此误导人。如果在同一轴上绘制,你会发现这些线根本没有交叉...大脑无法避免地将向上交叉解读为一个集合变得“大于”另一个集合,即使坐标轴上显示了数值。 - undefined
1
同意。我真的希望这个例子是针对一个真实的数据集,其中第二个轴是有意义的。但归根结底,我同意,这些图表很容易误导人。 - undefined

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