ggplot 中具有不同 x 值的两条曲线之间的阴影区域?
Shaded area between two curves with different x values in ggplot?
我知道在两条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
我最初的想法也是 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 值分组,也没有以其他方式排序。因此,它们不会 "belong" 成行,需要分成 3 组,然后可以将它们左连接回 x 值、y 值、y_min 和 [=39= 的逻辑行]:
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")
我知道在两条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
我最初的想法也是 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 值分组,也没有以其他方式排序。因此,它们不会 "belong" 成行,需要分成 3 组,然后可以将它们左连接回 x 值、y 值、y_min 和 [=39= 的逻辑行]:
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")