R:使用 ggplot2 平滑条形图中的合并数据
R: smoothing binned data in barplots with ggplot2
数据描述了商品(苹果和香蕉)在两个村庄(Villariba 和 Villabajo)之间道路沿线树木上的分布情况,该道路长 4000 多米。数据要么已经装箱(即每 500 米给出一次汇总),要么提供的位置有很大误差,因此按 500 米装箱是很自然的。我们希望通过内核平滑将它们处理并绘制为平滑的 post factum 分布。在 ggplot2
包中有两种明显的方法可以做到这一点。首先读取数据(长格式)。
library(ggplot2)
databas<-read.csv(text="dist,stuff,val
500,apples,10
1250,apples,25
1750,apples,55
2250,apples,45
2750,apples,25
3250,apples,10
3750,apples,5
500,bananas,7
1250,bananas,14
1750,bananas,20
2250,bananas,17
2750,bananas,10
3250,bananas,30
3750,bananas,20")
第一次尝试是 geom_col()
的无聊条形图。接下来,我们可以分别使用密度图 (geom_density()
) 和平滑曲线 (stat_smooth()
或等效的 geom_smooth()
) 中包含的两个 ggplot2 工具。三种方式实现如下:
p1<-ggplot(databas,aes(dist,val,fill=stuff,alpha=0.5))+geom_col(alpha=0.5,position="dodge")
p2<-ggplot(databas,aes(dist,val,fill=stuff))+stat_smooth(aes(y=val,x=dist),method="gam",se=FALSE,formula=y~s(x,k=7))
p3<-ggplot(databas,aes(dist,val,fill=stuff,alpha=0.5))+geom_density(stat="identity")
library(gridExtra)
grid.arrange(p1,p2,p3,nrow=3)
每种方法都有缺点。叠加的密度图(下图)是最理想的设计,但选项 stat="identity"
(因为数据已装箱)阻止创建美观的平滑分布,就像通常那样。 stat_smooth()
选项给出了几乎完美的曲线,但这些只是曲线。那么:如何结合密度图的着色和平滑函数的平滑?那是为了平滑geom_density()中的数据,还是在stat_smooth()
曲线下用半透明颜色填充space?
这是一种方法:
library(ggplot2)
p2 <- ggplot(databas, aes(dist ,val ,fill = stuff)) + stat_smooth(aes(y = val,x = dist), method = "gam",se = FALSE,formula = y ~ s(x, k = 7))
用ggplot_build
提取曲线
p2_build = ggplot_build(p2)
p2_fill <- data_frame(
x = p2_build$data[[1]]$x,
y = p2_build$data[[1]]$y,
group = factor(p2_build$data[[1]]$group, levels = c(1,2), labels = c("apples","bananas")))
用geom_area
添加颜色
p2 + geom_area(data = p2_fill[p2_fill$group == "apples", ],
aes(x=x, y=y), fill = "red", alpha = 0.2)+
geom_area(data = p2_fill[p2_fill$group == "bananas", ],
aes(x=x, y=y), fill = "blue", alpha = 0.2)
完整答案:
ggplot(databas, aes(dist, val, color = stuff))+
stat_smooth(aes(y = val,x = dist), method = "gam",se = FALSE, formula = y ~ s(x, k = 7))+
geom_area(data = p2_fill[p2_fill$group == "apples", ],
aes(x=x, y=y), fill = "#F8766D", alpha = 0.2, inherit.aes = F)+
geom_area(data = p2_fill[p2_fill$group == "bananas", ],
aes(x=x, y=y), fill = "#00BFC4", alpha = 0.2, inherit.aes = F)+
theme_classic()
如果您喜欢 gam
合身,可以在 geom_ribbon
中使用 stat = "smooth"
来绘制曲线。诀窍是将 ymin
设置为 0,将 ymax
设置为 ..y..
,这是由 stat_smooth
创建的特殊变量,即预测线。
ggplot(databas, aes(x = dist, y = val, fill = stuff)) +
geom_ribbon(stat = "smooth", aes(ymin = 0, ymax = ..y..), alpha = .5,
method = "gam", se=FALSE, formula = y ~ s(x, k = 7))
数据描述了商品(苹果和香蕉)在两个村庄(Villariba 和 Villabajo)之间道路沿线树木上的分布情况,该道路长 4000 多米。数据要么已经装箱(即每 500 米给出一次汇总),要么提供的位置有很大误差,因此按 500 米装箱是很自然的。我们希望通过内核平滑将它们处理并绘制为平滑的 post factum 分布。在 ggplot2
包中有两种明显的方法可以做到这一点。首先读取数据(长格式)。
library(ggplot2)
databas<-read.csv(text="dist,stuff,val
500,apples,10
1250,apples,25
1750,apples,55
2250,apples,45
2750,apples,25
3250,apples,10
3750,apples,5
500,bananas,7
1250,bananas,14
1750,bananas,20
2250,bananas,17
2750,bananas,10
3250,bananas,30
3750,bananas,20")
第一次尝试是 geom_col()
的无聊条形图。接下来,我们可以分别使用密度图 (geom_density()
) 和平滑曲线 (stat_smooth()
或等效的 geom_smooth()
) 中包含的两个 ggplot2 工具。三种方式实现如下:
p1<-ggplot(databas,aes(dist,val,fill=stuff,alpha=0.5))+geom_col(alpha=0.5,position="dodge")
p2<-ggplot(databas,aes(dist,val,fill=stuff))+stat_smooth(aes(y=val,x=dist),method="gam",se=FALSE,formula=y~s(x,k=7))
p3<-ggplot(databas,aes(dist,val,fill=stuff,alpha=0.5))+geom_density(stat="identity")
library(gridExtra)
grid.arrange(p1,p2,p3,nrow=3)
每种方法都有缺点。叠加的密度图(下图)是最理想的设计,但选项 stat="identity"
(因为数据已装箱)阻止创建美观的平滑分布,就像通常那样。 stat_smooth()
选项给出了几乎完美的曲线,但这些只是曲线。那么:如何结合密度图的着色和平滑函数的平滑?那是为了平滑geom_density()中的数据,还是在stat_smooth()
曲线下用半透明颜色填充space?
这是一种方法:
library(ggplot2)
p2 <- ggplot(databas, aes(dist ,val ,fill = stuff)) + stat_smooth(aes(y = val,x = dist), method = "gam",se = FALSE,formula = y ~ s(x, k = 7))
用ggplot_build
p2_build = ggplot_build(p2)
p2_fill <- data_frame(
x = p2_build$data[[1]]$x,
y = p2_build$data[[1]]$y,
group = factor(p2_build$data[[1]]$group, levels = c(1,2), labels = c("apples","bananas")))
用geom_area
p2 + geom_area(data = p2_fill[p2_fill$group == "apples", ],
aes(x=x, y=y), fill = "red", alpha = 0.2)+
geom_area(data = p2_fill[p2_fill$group == "bananas", ],
aes(x=x, y=y), fill = "blue", alpha = 0.2)
完整答案:
ggplot(databas, aes(dist, val, color = stuff))+
stat_smooth(aes(y = val,x = dist), method = "gam",se = FALSE, formula = y ~ s(x, k = 7))+
geom_area(data = p2_fill[p2_fill$group == "apples", ],
aes(x=x, y=y), fill = "#F8766D", alpha = 0.2, inherit.aes = F)+
geom_area(data = p2_fill[p2_fill$group == "bananas", ],
aes(x=x, y=y), fill = "#00BFC4", alpha = 0.2, inherit.aes = F)+
theme_classic()
如果您喜欢 gam
合身,可以在 geom_ribbon
中使用 stat = "smooth"
来绘制曲线。诀窍是将 ymin
设置为 0,将 ymax
设置为 ..y..
,这是由 stat_smooth
创建的特殊变量,即预测线。
ggplot(databas, aes(x = dist, y = val, fill = stuff)) +
geom_ribbon(stat = "smooth", aes(ymin = 0, ymax = ..y..), alpha = .5,
method = "gam", se=FALSE, formula = y ~ s(x, k = 7))