【问题标题】:Shaded area between two curves with different x values in ggplot?ggplot中具有不同x值的两条曲线之间的阴影区域?
【发布时间】:2020-03-19 19:11:45
【问题描述】:

我知道在两条具有相同x值的y曲线之间制作阴影区域如下:

    geom_ribbon(data=dataframe,aes(ymin = y_lwr, ymax = y_upr), fill = "grey")

但是,有谁知道我们如何绘制具有不同 x 值的两条曲线之间的阴影区域? 当下方曲线由(x_lwr, y_lwr) 定义且上方曲线由(x_upr, y_upr) 定义时 完整的数据集应该生成如下图:

我的示例数据和代码如下:

> head(df)
            y1     x1  y_lwr  x_lwr  y_upr  x_upr
    #> 1 11.60  67.01   4.97  86.28  14.54  58.17
    #> 2 11.32  68.57   4.51  88.99  13.74  61.67
    #> 3 10.76  71.63   4.15  91.29  13.00  64.74
    #> 4 10.19  75.52   3.82  92.69  12.35  67.83
    #> 5  9.91  77.33   3.60  94.19  11.71  70.84
    #> 6  9.62  79.14   3.46  94.90  11.21  73.33

    pltS <- ggplot(data=df, aes(x=df[,2], y=df[,1]))+
            ylab("log(y)")+ xlab("x")

    pltS <- pltS + geom_point(pch = 16, col="black", size=1)

    # upper and lower bands
    plt <- plt + geom_line(aes(x=df[,4], y=df[,3]), col="grey", size=1)
    plt <- plt + geom_line(aes(x=df[,6], y=df[,5]), col="grey", size=1)

    # x-axis & y-axis specifications
    plt <- plt + theme(aspect.ratio=1)+
                 scale_y_continuous(trans = 'log10')+
                 annotation_logticks(sides="l")+
                 scale_x_continuous(labels = function(x) paste0(x, "%"))
    plt

【问题讨论】:

  • 请查看How to make a great R reproducible example,以修改您的问题,并从您的数据中提取较小的样本(查看?dput())。发布您的数据或没有数据的图像会使我们难以为您提供帮助!
  • 查看geom_polygon
  • geom_polygon 没有给出我想要的图形!

标签: r ggplot2 data-visualization ribbon


【解决方案1】:

我最初的想法也是geom_polygon,但实际上,最简单的方法是在重塑数据后使用geom_ribbon

假设你有这样的东西:

library(tidyverse)

x1 <- seq(0, 2 * pi, 0.01)
x2 <- x1 + 0.005
y1 <- sin(x1)
y2 <- cos(x2)
df <- data.frame(x1, x2, y1, y2)

head(df)
#>     x1    x2          y1        y2
#> 1 0.00 0.005 0.000000000 0.9999875
#> 2 0.01 0.015 0.009999833 0.9998875
#> 3 0.02 0.025 0.019998667 0.9996875
#> 4 0.03 0.035 0.029995500 0.9993876
#> 5 0.04 0.045 0.039989334 0.9989877
#> 6 0.05 0.055 0.049979169 0.9984879

您有两组 x 值和两组 y 值。您可以简单地转换为长格式:

df2 <- pivot_longer(df, c("x1", "x2"))

head(df2)
#> # A tibble: 6 x 4
#>       y1    y2 name  value
#>    <dbl> <dbl> <chr> <dbl>
#> 1 0       1.00 x1    0    
#> 2 0       1.00 x2    0.005
#> 3 0.0100  1.00 x1    0.01 
#> 4 0.0100  1.00 x2    0.015
#> 5 0.0200  1.00 x1    0.02 
#> 6 0.0200  1.00 x2    0.025

这样您就可以正常使用geom_ribbon

ggplot(df2, aes(x = value)) + 
  geom_ribbon(aes(ymax = y1, ymin = y2), alpha = 0.2, colour = "black")


编辑

现在 OP 已链接到数据,更容易看出问题所在。这些行包含 3 组 x/y 值,分别代表最小线上的点、最大线上的点和中线上的点。但是,这三组点没有按 x 值分组,也没有其他排序。因此,它们不会按行“属于”在一起,需要分成 3 组,然后可以将它们左连接在一起,形成 x 值、y 值、y_min 和 y_max 的逻辑行:

library(tidyverse)

df_mid   <- df %>% transmute(x = round(x1, 1), y = y1) %>% arrange(x)
df_upper <- df %>% transmute(x = round(x_upr, 1), y_upr = y_upr)
df_lower <- df %>% transmute(x = round(x_lwr, 1), y_lwr = y_lwr)

left_join(df_mid, df_lower, by = "x")                    %>% 
  left_join(df_upper, by = "x")                          %>%
  filter(!duplicated(x) & !is.na(y_lwr) & !is.na(y_upr)) %>%
  ggplot(aes(x, y)) + 
   geom_line() +
   geom_ribbon(aes(ymax = y_lwr, ymin = y_upr), alpha = 0.2) +
   theme_bw() +
   theme(aspect.ratio = 1) +
   scale_y_continuous(trans = 'log10') +
   annotation_logticks(sides="l") +
   scale_x_continuous(labels = function(x) paste0(x, "%")) +
   ylab("log(y)") + xlab("x") 

【讨论】:

  • 您提供的解决方案没有创建相同的阴影色带,我在图中显示!
  • @Mahrokh 使用您现在提供的数据,我仍然得到了不错的结果。你在df2 &lt;- pivot_longer(df, c("x_lwr", "x_upr"))吗?
  • 我确实按照您的指示做了。但是,它不起作用!有没有办法可以向您发送完整的数据帧?另外,我在想是否存在一个函数,它为由 x_lwr 和 x_upr 组成的完整数组的每条曲线创建插值?
  • @Mahrokh 如果数据框不太大,您可以执行dput(df) 并将输出复制到您的问题中。否则,您可以在 cmets 中发布 Dropbox 或 Google 表格链接。
  • 感谢您的指导!这是电子表格的链接docs.google.com/spreadsheets/d/…
猜你喜欢
  • 1970-01-01
  • 2013-10-10
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-08
相关资源
最近更新 更多