当数据中只有 0 时,您可以强制 y 轴从 0 开始吗 (ggplot)

Can you force the y axis to start at 0 when there is only 0's in the data (ggplot)

提问人:dandrews 提问时间:10/13/2023 最后编辑:Axemandandrews 更新时间:10/14/2023 访问量:61

问:

我正在做一些数据探索,包括绘制时间序列。当我把数据拉下来时,有一些“结果”是真零。这些图包含许多站点,因此我使用 ggplot 的实用程序在多个站点上快速生成相同感兴趣参数的图形。我发现我可以强制 y 轴从这个堆栈帖子的 0 开始,但是当只有零值时,它会恢复为负 y 轴。facet_wrap

这里有一些代码,一个站点有零和非零数据(有效),另一个站点只有一个零,导致负 y 轴。

library(tidyverse)

dat <- structure(list(result = c(0, 0.01, 0, 0, 0.01, 0, 0, 0), date = structure(c(7755, 
7769, 7783, 7796, 7832, 7888, 7888, 841), class = "Date"), param_name = c("TP_mgL", 
"TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL"
), shortname = c("Black R. Boonville", "Black R. Boonville", 
"Black R. Boonville", "Black R. Boonville", "Black R. Boonville", 
"Black R. Boonville", "Black R. Boonville", "Independence R."
)), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame"
), na.action = structure(c(`4` = 4L, `5` = 5L, `7` = 7L, `8` = 8L, 
`9` = 9L, `11` = 11L, `12` = 12L, `13` = 13L, `14` = 14L, `21` = 21L, 
`23` = 23L, `24` = 24L, `25` = 25L, `27` = 27L, `32` = 32L, `36` = 36L, 
`53` = 53L, `54` = 54L, `55` = 55L, `57` = 57L, `58` = 58L, `60` = 60L, 
`61` = 61L, `64` = 64L, `65` = 65L, `68` = 68L, `69` = 69L, `70` = 70L, 
`72` = 72L, `73` = 73L, `85` = 85L, `104` = 104L, `105` = 105L, 
`109` = 109L, `110` = 110L, `123` = 123L, `127` = 127L, `129` = 129L, 
`130` = 130L, `135` = 135L, `136` = 136L, `137` = 137L, `138` = 138L, 
`141` = 141L, `143` = 143L, `144` = 144L, `145` = 145L, `146` = 146L, 
`151` = 151L, `153` = 153L, `154` = 154L, `155` = 155L, `156` = 156L, 
`157` = 157L, `161` = 161L, `164` = 164L, `165` = 165L, `166` = 166L, 
`172` = 172L, `178` = 178L, `179` = 179L, `184` = 184L, `208` = 208L, 
`209` = 209L, `257` = 257L, `264` = 264L, `268` = 268L, `287` = 287L, 
`292` = 292L, `293` = 293L, `295` = 295L, `296` = 296L, `297` = 297L, 
`304` = 304L, `320` = 320L, `329` = 329L, `330` = 330L, `331` = 331L, 
`332` = 332L, `333` = 333L, `334` = 334L, `335` = 335L, `336` = 336L, 
`337` = 337L, `338` = 338L, `339` = 339L, `340` = 340L, `341` = 341L, 
`343` = 343L, `344` = 344L, `349` = 349L, `350` = 350L, `351` = 351L, 
`365` = 365L, `371` = 371L, `374` = 374L, `378` = 378L, `383` = 383L, 
`390` = 390L, `391` = 391L, `397` = 397L, `400` = 400L, `401` = 401L, 
`402` = 402L, `410` = 410L, `412` = 412L, `413` = 413L, `414` = 414L, 
`415` = 415L, `416` = 416L, `417` = 417L, `418` = 418L, `419` = 419L, 
`421` = 421L, `422` = 422L, `424` = 424L, `425` = 425L, `430` = 430L, 
`431` = 431L, `446` = 446L, `451` = 451L, `452` = 452L, `457` = 457L, 
`458` = 458L, `459` = 459L, `463` = 463L, `470` = 470L, `480` = 480L, 
`493` = 493L, `494` = 494L, `496` = 496L, `498` = 498L, `499` = 499L, 
`500` = 500L, `501` = 501L, `506` = 506L, `507` = 507L, `508` = 508L, 
`512` = 512L, `513` = 513L, `514` = 514L, `515` = 515L, `516` = 516L, 
`539` = 539L, `563` = 563L, `564` = 564L, `565` = 565L, `569` = 569L, 
`570` = 570L, `571` = 571L, `574` = 574L, `575` = 575L, `581` = 581L, 
`587` = 587L, `593` = 593L, `600` = 600L, `605` = 605L, `610` = 610L, 
`750` = 750L, `761` = 761L, `776` = 776L, `837` = 837L, `855` = 855L, 
`861` = 861L, `881` = 881L), class = "omit"))

ggplot(dat) +
  geom_point(aes(x=date,y=result,color=param_name),
             pch=19) +
  scale_y_continuous(limits = c(0,NA)) +
  theme_bw() +
  theme(element_blank()) +
  facet_wrap(facets = ~shortname,
             scales = 'free')  +
  scale_x_date(date_labels = '%y') +
  theme(legend.position = 'none') +
  xlab('Year') +
  ylab(expression(paste('Total Phosphorus (',mu,'/g/l)'))) 

enter image description here

我试过 and,但都没有强制单个零图从 0 开始。想知道是否有任何方法可以实现这一目标?expand_limits(y=0)scale_y_continuous(limits=c(0,NA))

编辑多亏了 Seth 的评论,我意识到我的问题存在一个陷阱。在实际数据中,数据在 y 方向上的范围足够大,因此我需要保持 y 刻度自由。Seth 的一个很好的解决方案是只释放 x 尺度,以便在代码中实现:facet_wrap

facet_wrap(facets~shortname,
           scales='free_x')

有效,但随后来自站点的大部分数据都与 X 轴相撞。

这是包含完整数据和自由 y 轴的图:enter image description here

这是只有 X 轴空闲的:enter image description here

R GGPLOT2 分面

评论

2赞 Seth 10/13/2023
嗨,@dandrews。如果仅释放跨小平面的 x 轴比例,则可以实现此目的,并可以选择删除比例。在集合中。scale_y_continuousfacet_wrapscales = "free_x"
0赞 stefan_aus_hannover 10/13/2023
@Seth应该把这当作一个答案
0赞 dandrews 10/13/2023
@Seth很好的解决方案,谢谢。但是,我确实需要 y 量表也是免费的。我会更新问题。

答:

2赞 Seth 10/13/2023 #1

原始答案

我们可以有选择地只释放 x 轴。面板将共享一个公共 y 轴,任何仅点为 0 的面板仍将受到其他数据范围的约束。facets

在 中,设置 ,您可以删除 。facet_wrapscales = "free_x"scale_y_continuous

library(tidyverse)


ggplot(dat) +
  geom_point(aes(x=date,y=result,color=param_name),
             pch=19) +
  theme_bw() +
  theme(element_blank()) +
  facet_wrap(facets = ~shortname,
             scales = 'free_x')  +
  scale_x_date(date_labels = '%y') +
  theme(legend.position = 'none') +
  xlab('Year') +
  ylab(expression(paste('Total Phosphorus (',mu,'/g/l)'))) 

更新的答案

使用它可以指定每个面的比例,并且该软件包提供了几种方法来解决这个问题。ggh4x

对于此示例,我在提供的示例中添加了一些虚假数据,并在末尾包含这些数据。

我首先创建一个列表,列出我想要应用 y 轴限制的列表。在函数中,添加的是我应用指定 .我选择使用全范围的 ,但您可以根据需要进行调整。shortnamesggplotscale_y_facetlimitresult

library(tidyverse)
library(ggh4x)

zero_dat <- dat %>%
  filter(sum(abs(result)) == 0, .by = shortname) %>% pull(shortname)

ggplot(dat) +
  geom_point(aes(x=date,y=result,color=param_name),
             pch=19) +
  theme_bw() +
  theme(element_blank()) +
  facet_wrap(facets = ~shortname,
             scales = 'free')  +
  scale_x_date(date_labels = '%y') +
  scale_y_facet(
    shortname %in% zero_dat,
    limits = range(dat$result)) +
  theme(legend.position = 'none') +
  xlab('Year') +
  ylab(expression(paste('Total Phosphorus (',mu,'/g/l)'))) 

数据

dat <- structure(list(result = c(0, 0.01, 0, 0, 0.01, 0, 0, 0, 4, 1, 
                                 5, 10, 0), date = structure(c(7755, 7769, 7783, 7796, 7832, 7888, 
                                                               7888, 841, 7755, 8160, 8192, 8770, 9494), class = "Date"), param_name = c("TP_mgL", 
                                                                                                                                         "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", 
                                                                                                                                         "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL", "TP_mgL"), shortname = c("Black R. Boonville", 
                                                                                                                                                                                                          "Black R. Boonville", "Black R. Boonville", "Black R. Boonville", 
                                                                                                                                                                                                          "Black R. Boonville", "Black R. Boonville", "Black R. Boonville", 
                                                                                                                                                                                                          "Independence R.", "Fake Data", "Fake Data", "Fake Data", "Fake Data", 
                                                                                                                                                                                                          "Fake Data")), row.names = c(NA, -13L), class = c("tbl_df", "tbl", 
                                                                                                                                                                                                                                                            "data.frame"), na.action = structure(c(`4` = 4L, `5` = 5L, `7` = 7L, 
                                                                                                                                                                                                                                                                                                   `8` = 8L, `9` = 9L, `11` = 11L, `12` = 12L, `13` = 13L, `14` = 14L, 
                                                                                                                                                                                                                                                                                                   `21` = 21L, `23` = 23L, `24` = 24L, `25` = 25L, `27` = 27L, `32` = 32L, 
                                                                                                                                                                                                                                                                                                   `36` = 36L, `53` = 53L, `54` = 54L, `55` = 55L, `57` = 57L, `58` = 58L, 
                                                                                                                                                                                                                                                                                                   `60` = 60L, `61` = 61L, `64` = 64L, `65` = 65L, `68` = 68L, `69` = 69L, 
                                                                                                                                                                                                                                                                                                   `70` = 70L, `72` = 72L, `73` = 73L, `85` = 85L, `104` = 104L, 
                                                                                                                                                                                                                                                                                                   `105` = 105L, `109` = 109L, `110` = 110L, `123` = 123L, `127` = 127L, 
                                                                                                                                                                                                                                                                                                   `129` = 129L, `130` = 130L, `135` = 135L, `136` = 136L, `137` = 137L, 
                                                                                                                                                                                                                                                                                                   `138` = 138L, `141` = 141L, `143` = 143L, `144` = 144L, `145` = 145L, 
                                                                                                                                                                                                                                                                                                   `146` = 146L, `151` = 151L, `153` = 153L, `154` = 154L, `155` = 155L, 
                                                                                                                                                                                                                                                                                                   `156` = 156L, `157` = 157L, `161` = 161L, `164` = 164L, `165` = 165L, 
                                                                                                                                                                                                                                                                                                   `166` = 166L, `172` = 172L, `178` = 178L, `179` = 179L, `184` = 184L, 
                                                                                                                                                                                                                                                                                                   `208` = 208L, `209` = 209L, `257` = 257L, `264` = 264L, `268` = 268L, 
                                                                                                                                                                                                                                                                                                   `287` = 287L, `292` = 292L, `293` = 293L, `295` = 295L, `296` = 296L, 
                                                                                                                                                                                                                                                                                                   `297` = 297L, `304` = 304L, `320` = 320L, `329` = 329L, `330` = 330L, 
                                                                                                                                                                                                                                                                                                   `331` = 331L, `332` = 332L, `333` = 333L, `334` = 334L, `335` = 335L, 
                                                                                                                                                                                                                                                                                                   `336` = 336L, `337` = 337L, `338` = 338L, `339` = 339L, `340` = 340L, 
                                                                                                                                                                                                                                                                                                   `341` = 341L, `343` = 343L, `344` = 344L, `349` = 349L, `350` = 350L, 
                                                                                                                                                                                                                                                                                                   `351` = 351L, `365` = 365L, `371` = 371L, `374` = 374L, `378` = 378L, 
                                                                                                                                                                                                                                                                                                   `383` = 383L, `390` = 390L, `391` = 391L, `397` = 397L, `400` = 400L, 
                                                                                                                                                                                                                                                                                                   `401` = 401L, `402` = 402L, `410` = 410L, `412` = 412L, `413` = 413L, 
                                                                                                                                                                                                                                                                                                   `414` = 414L, `415` = 415L, `416` = 416L, `417` = 417L, `418` = 418L, 
                                                                                                                                                                                                                                                                                                   `419` = 419L, `421` = 421L, `422` = 422L, `424` = 424L, `425` = 425L, 
                                                                                                                                                                                                                                                                                                   `430` = 430L, `431` = 431L, `446` = 446L, `451` = 451L, `452` = 452L, 
                                                                                                                                                                                                                                                                                                   `457` = 457L, `458` = 458L, `459` = 459L, `463` = 463L, `470` = 470L, 
                                                                                                                                                                                                                                                                                                   `480` = 480L, `493` = 493L, `494` = 494L, `496` = 496L, `498` = 498L, 
                                                                                                                                                                                                                                                                                                   `499` = 499L, `500` = 500L, `501` = 501L, `506` = 506L, `507` = 507L, 
                                                                                                                                                                                                                                                                                                   `508` = 508L, `512` = 512L, `513` = 513L, `514` = 514L, `515` = 515L, 
                                                                                                                                                                                                                                                                                                   `516` = 516L, `539` = 539L, `563` = 563L, `564` = 564L, `565` = 565L, 
                                                                                                                                                                                                                                                                                                   `569` = 569L, `570` = 570L, `571` = 571L, `574` = 574L, `575` = 575L, 
                                                                                                                                                                                                                                                                                                   `581` = 581L, `587` = 587L, `593` = 593L, `600` = 600L, `605` = 605L, 
                                                                                                                                                                                                                                                                                                   `610` = 610L, `750` = 750L, `761` = 761L, `776` = 776L, `837` = 837L, 
                                                                                                                                                                                                                                                                                                   `855` = 855L, `861` = 861L, `881` = 881L), class = "omit"))

评论

0赞 dandrews 10/13/2023
谢谢,当我提出这个问题时,这是一个很好的解决方案。为了简化,我省略了可能不需要的数据,但最好让 y 轴自由,这样我们就可以可视化接近零的更好数据。我为问题添加了更新。如果您有任何建议可以保持 y 轴自由,我全都听进去了!也许在当前的 ggplot 环境中是不可能的。
0赞 Seth 10/14/2023
嗨,@dandrews。请参阅答案的更新部分,了解一种按分面自定义比例的复杂方法。
0赞 dandrews 10/14/2023
我认为这是一个选项,但我看到的版本是一个接一个地通过的。这种将数据中只有 0 的站点分解的解决方案似乎是目前最好的选择。干杯