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))