我试图根据用户的选择以不同的方式生成一个带有两个垂直轴的 ggplot。一个选择允许用户反转每个轴。另一种选择允许他们在每个轴上的系列的点和条之间进行选择。当主(左侧)y 轴反转并且辅助(右侧)数据设置为显示为条形时,我遇到了问题。在这种情况下,条形图从图的顶部而不是底部开始,因为它们应该基于次轴方向。
双方都有积分,一切看起来都很好:
点没有底部或顶部,只有一个坐标,因此它们看起来不错。但是对于右侧的条形,一旦我反转左侧 y 轴,条形就会从顶部开始垂直翻转并向下生长,直到到达相应的坐标:
(请忽略图例符号,我可以自己更正,但会扩展 MRE 的代码)。
对于我从其他帖子中学到的东西(例如,[A] https://stackoverflow.com/a/3101876/12372421, [B] https://stackoverflow.com/a/59957110/12372421, ) ggplot 不允许处理两个完全独立的垂直轴,而只是处理一个辅助轴,它是主轴的重新缩放。这就是我遇到的问题的根源。我的条形图将左侧零作为它们的最小 y 值。
我只希望当我还选择反转辅助轴时才会发生这种情况,但这里的情况并非如此。如果仅左侧 y 轴反转,我希望右侧条从图的底部开始,即右侧的零。
MRE
** Data
df1 <- data.frame(ID = c("A", "A", "A", "A", "B", "B", "B", "B"),
Date = structure(c(19078, 19085, 19092, 19099, 19078, 19085, 19092, 19099), class = "Date"),
Val = c(236, 221, 187, 136, 77, 100, 128, 180))
df2 <- data.frame(ID = c("J", "J", "J", "J", "K", "K", "K", "K"),
Date = structure(c(19078, 19085, 19092, 19099, 19078, 19085, 19092, 19099), class = "Date"),
Val = c(478, 500, 549, 479, 73, 5, 15, 74))
** 两侧都有点的工作案例
library(dplyr)
library(ggplot2)
# prepare y2 scaled data
ylim1 <- rev(range(df1$Val))
ylim2 <- range(df2$Val)
scale_y2.1 <- function(y, ylim1, ylim2) {
ylim1[1] + (ylim1[2] - ylim1[1]) *(y - ylim2[1])/(ylim2[2] - ylim2[1])
}
dfAll <- full_join(df1, df2, by = c("ID", "Date"), suffix = c("1", "2"))
y2.scl <- scale_y2.1(dfAll$Val2, ylim1, ylim2)
dfAll <- dfAll %>% mutate(Val2_scl = y2.scl)
# prepare y2 ticks and scaled breaks
labs2 <- pretty(ylim2)
brks2 <- scale_y2.1(labs2, ylim1, ylim2)
# generate plot
ggplot(dfAll) +
geom_point(aes(x = Date, y = Val1, color = ID, group = ID), na.rm = TRUE) +
geom_point(aes(x = Date, y = Val2_scl, color = ID, group = ID), na.rm = TRUE) +
scale_y_continuous(trans = "reverse", sec.axis = dup_axis(breaks = rev(brks2),
labels = rev(labs2),
name = "Val2"))
** 箱子破损,右侧有横条
# generate plot
ggplot(dfAll) +
geom_point(aes(x = Date, y = Val1, color = ID, group = ID), na.rm = TRUE) +
geom_bar(aes(x = Date, y = Val2_scl, fill = ID, group = ID), na.rm = TRUE,
stat = "identity", position = position_dodge(preserve = "single")) +
scale_y_continuous(trans = "reverse", sec.axis = dup_axis(breaks = rev(brks2),
labels = rev(labs2),
name = "Val2"))
** 这个答案 https://stackoverflow.com/a/64974716/12372421似乎有一些适合我的案例的潜力。它有一个相反的左侧轴,并且条形仍然从下向上生长。不幸的是,答案没有对所做的事情或为什么有效进行任何解释。这只是工作代码。我无法调整它以适合我。
** 这另一个答案 https://stackoverflow.com/a/55348769/12372421也可以工作,因为geom_linerange()
让我们指定最小和最大 y 值。但是,在这种情况下,需要手动设置线条范围的宽度以使它们看起来像条形。在我的设置中,要绘制的系列数量可以从几个到超过 20 个不等。因此,手动设置条形宽度似乎不太稳健/实用。