R 如何在插值数据图的边缘绘制原始数据的直方图

R 如何在插值数据图的边缘绘制原始数据的直方图,r,plot,ggplot2,histogram,R,Plot,Ggplot2,Histogram,我想在同一个图中显示插值数据和每个预测值的原始数据直方图。我在其他类似的线程中看到,人们解释了如何对散点图中显示的相同数据进行边缘直方图,在这种情况下,直方图基于其他数据(原始数据) 假设我们在钻石数据集中看到价格与克拉和表的关系: library(ggplot2) p = ggplot(diamonds, aes(x = carat, y = table, color = price)) + geom_point() 我们可以添加一个边际频率图,例如ggMarginal library(gg

我想在同一个图中显示插值数据和每个预测值的原始数据直方图。我在其他类似的线程中看到,人们解释了如何对散点图中显示的相同数据进行边缘直方图,在这种情况下,直方图基于其他数据(原始数据)

假设我们在钻石数据集中看到价格与克拉和表的关系:

library(ggplot2)
p = ggplot(diamonds, aes(x = carat, y = table, color = price)) + geom_point()
我们可以添加一个边际频率图,例如ggMarginal

library(ggExtra)    
ggMarginal(p)

我们如何添加类似于预测钻石价格的瓷砖图

library(mgcv)
model = gam(price ~ s(table, carat), data = diamonds)
newdat = expand.grid(seq(55,75, 5), c(1:4))
names(newdat) = c("table", "carat")
newdat$predicted_price = predict(model, newdat)

ggplot(newdat,aes(x = carat, y = table, fill = predicted_price)) + 
    geom_tile()

理想情况下,直方图甚至超出了tileplot的边界,因为这些数据点也会影响预测。然而,我已经非常高兴知道如何为tileplot中显示的范围绘制直方图。(可能超出范围的值可以用不同的颜色添加到极值。)

注:我设法或多或少地将柱状图与平铺图侧面的边距对齐,使用链接中可接受答案的方法,但前提是我删除了所有类型的标签。如果可能的话,保留颜色图例会特别好

编辑: eipi10提供了一个极好的解决方案。我尝试稍微修改它,以数字形式添加样本大小,并以图形方式显示打印范围之外的值,因为它们也会影响插值。 我打算在侧面的直方图中以不同的颜色包含它们。在此,我试图将它们计算到绘图范围的下限和上限。我还尝试在绘图的某个地方用数字绘制样本大小。然而,我在这两方面都失败了

这是我试图以图形方式说明绘图区域以外的样本大小:

plot_data = diamonds
plot_data <- transform(plot_data, carat_range = ifelse(carat < 1 | carat > 4, "outside", "within"))
plot_data <- within(plot_data, carat[carat < 1] <- 1)
plot_data <- within(plot_data, carat[carat > 4] <- 4)
plot_data$carat_range = as.factor(plot_data$carat_range)

p2 = ggplot(plot_data, aes(carat, fill = carat_range)) +
    geom_histogram() +
    thm +
    coord_cartesian(xlim=xrng)

我很乐意在其中一项或两项任务上获得帮助(将样本大小添加为文本,并以不同颜色添加打印范围以外的值)。

根据您的评论,最好的方法可能是滚动您自己的布局。下面是一个例子。我们将边缘图创建为单独的ggplot对象,并与主图一起进行布局。我们还提取了传说,并将其置于边缘情节之外

组织

更新:关于您对绘图间距的评论:这是
plot\u grid
的致命弱点,我不知道是否有办法解决。另一个选项是来自实验性
egg
包的
ggarrange
,它不会在绘图之间增加太多空间。此外,您需要先保存
ggarrange
的输出,然后用图例布局保存的对象。如果在
网格内运行
ggarrange
。arrange
将获得两个重叠的绘图副本:

# devtools::install_github('baptiste/egg')
library(egg) 

pobj = ggarrange(p2, ggplot(), p1, p3, 
                 ncol=2, widths=c(4,1), heights=c(1,4))

grid.arrange(pobj, leg, widths=c(6,1))

哪个包裹在里面?对不起。我忘了在上面注明,是在ggExtra。谢谢你的回答。但是,它们仍然没有正确对齐,因为克拉和表在新达特和钻石中有不同的范围。非常感谢!很好的回答:-)你也知道如何减少直线图和主图之间的空白吗?太好了。这看起来很漂亮!我试着稍微修改一下你的情节,但我显然不太明白你做了什么。你能看看我上面的尝试吗?很抱歉,我被这件事弄糊涂了。
library(ggplot2)
library(cowplot)

# Function to extract legend
#https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs
g_legend<-function(a.gplot){
  tmp <- ggplot_gtable(ggplot_build(a.gplot))
  leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
  legend <- tmp$grobs[[leg]]
  return(legend) }

thm = list(theme_void(),
           guides(fill=FALSE),
           theme(plot.margin=unit(rep(0,4), "lines")))

xrng = c(0.6,4.4)
yrng = c(53,77)
p1 = ggplot(newdat, aes(x = carat, y = table, fill = predicted_price)) + 
  geom_tile() +
  theme_classic() +
  coord_cartesian(xlim=xrng, ylim=yrng)

leg = g_legend(p1)

p1 = p1 + thm[-1]

p2 = ggplot(diamonds, aes(carat)) +
  geom_line(stat="density") +
  thm +
  coord_cartesian(xlim=xrng)

p3 = ggplot(diamonds, aes(table)) +
  geom_line(stat="density") +
  thm + 
  coord_flip(xlim=yrng)

plot_grid(
  plot_grid(plotlist=list(p2, ggplot(), p1, p3), ncol=2, 
            rel_widths=c(4,1), rel_heights=c(1,4), align="hv", scale=1.1),
  leg, rel_widths=c(5,1))
# devtools::install_github('baptiste/egg')
library(egg) 

pobj = ggarrange(p2, ggplot(), p1, p3, 
                 ncol=2, widths=c(4,1), heights=c(1,4))

grid.arrange(pobj, leg, widths=c(6,1))