Seb*_*Seb 130 r histogram scatter-plot ggplot2
有没有办法用边缘直方图创建散点图,就像下面的示例一样ggplot2?在Matlab中它是scatterhist()函数,并且R也存在等价物.但是,我还没有看到ggplot2.

我开始尝试创建单个图形,但不知道如何正确排列它们.
require(ggplot2)
x<-rnorm(300)
y<-rt(300,df=2)
xy<-data.frame(x,y)
xhist <- qplot(x, geom="histogram") + scale_x_continuous(limits=c(min(x),max(x))) + opts(axis.text.x = theme_blank(), axis.title.x=theme_blank(), axis.ticks = theme_blank(), aspect.ratio = 5/16, axis.text.y = theme_blank(), axis.title.y=theme_blank(), background.colour="white")
yhist <- qplot(y, geom="histogram") + coord_flip() + opts(background.fill = "white", background.color ="black")
yhist <- yhist + scale_x_continuous(limits=c(min(x),max(x))) + opts(axis.text.x = theme_blank(), axis.title.x=theme_blank(), axis.ticks = theme_blank(), aspect.ratio = 16/5, axis.text.y = theme_blank(), axis.title.y=theme_blank() )
scatter <- qplot(x,y, data=xy) + scale_x_continuous(limits=c(min(x),max(x))) + scale_y_continuous(limits=c(min(y),max(y)))
none <- qplot(x,y, data=xy) + geom_blank()
Run Code Online (Sandbox Code Playgroud)
并使用此处发布的功能安排它们.但长话短说:有没有办法创建这些图表?
42-*_*42- 110
这不是一个完全响应的答案,但它非常简单.它说明了显示边际密度的另一种方法,以及如何将alpha级别用于支持透明度的图形输出:
scatter <- qplot(x,y, data=xy) +
scale_x_continuous(limits=c(min(x),max(x))) +
scale_y_continuous(limits=c(min(y),max(y))) +
geom_rug(col=rgb(.5,0,0,alpha=.2))
scatter
Run Code Online (Sandbox Code Playgroud)

oeo*_*o4b 88
该gridExtra包应该在这里工作.首先制作每个ggplot对象:
hist_top <- ggplot()+geom_histogram(aes(rnorm(100)))
empty <- ggplot()+geom_point(aes(1,1), colour="white")+
theme(axis.ticks=element_blank(),
panel.background=element_blank(),
axis.text.x=element_blank(), axis.text.y=element_blank(),
axis.title.x=element_blank(), axis.title.y=element_blank())
scatter <- ggplot()+geom_point(aes(rnorm(100), rnorm(100)))
hist_right <- ggplot()+geom_histogram(aes(rnorm(100)))+coord_flip()
Run Code Online (Sandbox Code Playgroud)
然后使用grid.arrange函数:
grid.arrange(hist_top, empty, scatter, hist_right, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))
Run Code Online (Sandbox Code Playgroud)

Dea*_*ali 85
这可能有点晚了,但我决定为此创建一个package(ggExtra),因为它涉及一些代码并且编写起来可能很乏味.该软件包还试图解决一些常见问题,例如确保即使有标题或文本被放大,这些图仍将是彼此内联的.
基本思想类似于这里给出的答案,但它有点超出了这个范围.以下是如何将边缘直方图添加到1000个点的随机集中的示例.希望这可以使将来更容易添加直方图/密度图.
library(ggplot2)
df <- data.frame(x = rnorm(1000, 50, 10), y = rnorm(1000, 50, 10))
p <- ggplot(df, aes(x, y)) + geom_point() + theme_classic()
ggExtra::ggMarginal(p, type = "histogram")
Run Code Online (Sandbox Code Playgroud)

Lor*_*rai 44
一个补充,只是为了节省一些人在我们之后这样做的搜索时间.
传说,轴标签,轴文本,刻度使得情节相互偏离,因此您的情节将看起来丑陋且不一致.
您可以使用其中一些主题设置来更正此问题,
+theme(legend.position = "none",
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
plot.margin = unit(c(3,-5.5,4,3), "mm"))
Run Code Online (Sandbox Code Playgroud)
和对齐尺度,
+scale_x_continuous(breaks = 0:6,
limits = c(0,6),
expand = c(.05,.05))
Run Code Online (Sandbox Code Playgroud)
所以结果看起来还不错:

Ben*_*Ben 28
就分配边际指标的一般精神而言,BondedDust的答案只是一个非常小的变化.
Edward Tufte将这种地毯图的使用称为"点划线图",并且在VDQI中有一个例子,即使用轴线来指示每个变量的范围.在我的示例中,轴标签和网格线也指示数据的分布.标签位于Tukey的五个数字摘要(最小,下铰链,中位数,上铰链,最大值)的值,给出了每个变量的传播的快速印象.
因此,这五个数字是箱线图的数字表示.这有点棘手,因为不均匀间隔的网格线表明轴具有非线性比例(在这个例子中它们是线性的).也许最好省略网格线或强制它们在常规位置,并让标签显示五个数字摘要.
x<-rnorm(300)
y<-rt(300,df=10)
xy<-data.frame(x,y)
require(ggplot2); require(grid)
# make the basic plot object
ggplot(xy, aes(x, y)) +
# set the locations of the x-axis labels as Tukey's five numbers
scale_x_continuous(limit=c(min(x), max(x)),
breaks=round(fivenum(x),1)) +
# ditto for y-axis labels
scale_y_continuous(limit=c(min(y), max(y)),
breaks=round(fivenum(y),1)) +
# specify points
geom_point() +
# specify that we want the rug plot
geom_rug(size=0.1) +
# improve the data/ink ratio
theme_set(theme_minimal(base_size = 18))
Run Code Online (Sandbox Code Playgroud)

j3y*_*ypi 15
我尝试了这些选项,但对结果或达到目标所需的凌乱代码并不满意。幸运的是,Thomas Lin Pedersen 刚刚开发了一个名为patchwork的包,它以非常优雅的方式完成工作。
如果要创建带有边际直方图的散点图,首先必须分别创建这三个图。
library(ggplot2)
x <- rnorm(300)
y <- rt(300, df = 2)
xy <- data.frame(x, y)
plot1 <- ggplot(xy, aes(x = x, y = y)) +
geom_point()
dens1 <- ggplot(xy, aes(x = x)) +
geom_histogram(color = "black", fill = "white") +
theme_void()
dens2 <- ggplot(xy, aes(x = y)) +
geom_histogram(color = "black", fill = "white") +
theme_void() +
coord_flip()
Run Code Online (Sandbox Code Playgroud)
剩下要做的唯一一件事就是用一个简单+的函数添加这些图,并用函数指定布局plot_layout()。
library(patchwork)
dens1 + plot_spacer() + plot1 + dens2 +
plot_layout(
ncol = 2,
nrow = 2,
widths = c(4, 1),
heights = c(1, 4)
)
Run Code Online (Sandbox Code Playgroud)
该函数plot_spacer()在右上角添加一个空图。所有其他论点都应该是不言自明的。
由于直方图在很大程度上取决于所选的 binwidth,因此人们可能会争辩说更喜欢密度图。通过一些小的修改,人们会得到一个漂亮的图,例如眼动追踪数据。
library(ggpubr)
plot1 <- ggplot(df, aes(x = Density, y = Face_sum, color = Group)) +
geom_point(aes(color = Group), size = 3) +
geom_point(shape = 1, color = "black", size = 3) +
stat_smooth(method = "lm", fullrange = TRUE) +
geom_rug() +
scale_y_continuous(name = "Number of fixated faces",
limits = c(0, 205), expand = c(0, 0)) +
scale_x_continuous(name = "Population density (lg10)",
limits = c(1, 4), expand = c(0, 0)) +
theme_pubr() +
theme(legend.position = c(0.15, 0.9))
dens1 <- ggplot(df, aes(x = Density, fill = Group)) +
geom_density(alpha = 0.4) +
theme_void() +
theme(legend.position = "none")
dens2 <- ggplot(df, aes(x = Face_sum, fill = Group)) +
geom_density(alpha = 0.4) +
theme_void() +
theme(legend.position = "none") +
coord_flip()
dens1 + plot_spacer() + plot1 + dens2 +
plot_layout(ncol = 2, nrow = 2, widths = c(4, 1), heights = c(1, 4))
Run Code Online (Sandbox Code Playgroud)
虽然此时没有提供数据,但基本原则应该是清楚的。
Hav*_*v0k 10
由于在比较不同的组时这种情节没有令人满意的解决方案,我写了一个函数来做到这一点.
它适用于分组和未分组数据,并接受其他图形参数:
marginal_plot(x = iris$Sepal.Width, y = iris$Sepal.Length)
Run Code Online (Sandbox Code Playgroud)
marginal_plot(x = Sepal.Width, y = Sepal.Length, group = Species, data = iris, bw = "nrd", lm_formula = NULL, xlab = "Sepal width", ylab = "Sepal length", pch = 15, cex = 0.5)
Run Code Online (Sandbox Code Playgroud)
小智 9
这是一个老问题,但我认为在这里发布更新会很有用,因为我最近遇到了同样的问题(感谢 Stefanie Mueller 的帮助!)。
使用 gridExtra 的最受好评的答案有效,但正如评论中指出的那样,对齐轴很困难/很麻烦。现在可以使用 ggExtra 包中的 ggMarginal 命令解决这个问题,如下所示:
#load packages
library(tidyverse) #for creating dummy dataset only
library(ggExtra)
#create dummy data
a = round(rnorm(1000,mean=10,sd=6),digits=0)
b = runif(1000,min=1.0,max=1.6)*a
b = b+runif(1000,min=9,max=15)
DummyData <- data.frame(var1 = b, var2 = a) %>%
filter(var1 > 0 & var2 > 0)
#plot
p = ggplot(DummyData, aes(var1, var2)) + geom_point(alpha=0.3)
ggMarginal(p, type = "histogram")
Run Code Online (Sandbox Code Playgroud)
我发现该软件包(ggpubr)对于该问题似乎非常有效,并且考虑了显示数据的几种可能性。
该包的链接在这里,在此链接中,您将找到一个使用它的不错的教程。为了完整起见,我附上我复制的示例之一。
我首先安装了该软件包(需要安装devtools)
if(!require(devtools)) install.packages("devtools")
devtools::install_github("kassambara/ggpubr")
Run Code Online (Sandbox Code Playgroud)
对于显示不同组的不同直方图的特定示例,它与以下内容有关ggExtra:“的一个局限性ggExtra是它不能处理散点图和边际图中的多个组。在下面的R代码中,我们提供了解决方案cowplot。” 就我而言,我必须安装后一个软件包:
install.packages("cowplot")
Run Code Online (Sandbox Code Playgroud)
我遵循了这段代码:
# Scatter plot colored by groups ("Species")
sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width",
color = "Species", palette = "jco",
size = 3, alpha = 0.6)+
border()
# Marginal density plot of x (top panel) and y (right panel)
xplot <- ggdensity(iris, "Sepal.Length", fill = "Species",
palette = "jco")
yplot <- ggdensity(iris, "Sepal.Width", fill = "Species",
palette = "jco")+
rotate()
# Cleaning the plots
sp <- sp + rremove("legend")
yplot <- yplot + clean_theme() + rremove("legend")
xplot <- xplot + clean_theme() + rremove("legend")
# Arranging the plot using cowplot
library(cowplot)
plot_grid(xplot, NULL, sp, yplot, ncol = 2, align = "hv",
rel_widths = c(2, 1), rel_heights = c(1, 2))
Run Code Online (Sandbox Code Playgroud)
对我来说很好
为了建立在@alf-pascu 的答案的基础上,手动设置每个图并安排它们 cowplot在主要图和边际图方面都具有很大的灵活性(与其他一些解决方案相比)。按组分布就是一个例子。将主图更改为二维密度图是另一回事。
下面创建一个散点图(正确对齐)边缘直方图。
library("ggplot2")
library("cowplot")
# Set up scatterplot
scatterplot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point(size = 3, alpha = 0.6) +
guides(color = FALSE) +
theme(plot.margin = margin())
# Define marginal histogram
marginal_distribution <- function(x, var, group) {
ggplot(x, aes_string(x = var, fill = group)) +
geom_histogram(bins = 30, alpha = 0.4, position = "identity") +
# geom_density(alpha = 0.4, size = 0.1) +
guides(fill = FALSE) +
theme_void() +
theme(plot.margin = margin())
}
# Set up marginal histograms
x_hist <- marginal_distribution(iris, "Sepal.Length", "Species")
y_hist <- marginal_distribution(iris, "Sepal.Width", "Species") +
coord_flip()
# Align histograms with scatterplot
aligned_x_hist <- align_plots(x_hist, scatterplot, align = "v")[[1]]
aligned_y_hist <- align_plots(y_hist, scatterplot, align = "h")[[1]]
# Arrange plots
plot_grid(
aligned_x_hist
, NULL
, scatterplot
, aligned_y_hist
, ncol = 2
, nrow = 2
, rel_heights = c(0.2, 1)
, rel_widths = c(1, 0.2)
)
Run Code Online (Sandbox Code Playgroud)
要绘制二维密度图,只需更改主图即可。
# Set up 2D-density plot
contour_plot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
stat_density_2d(aes(alpha = ..piece..)) +
guides(color = FALSE, alpha = FALSE) +
theme(plot.margin = margin())
# Arrange plots
plot_grid(
aligned_x_hist
, NULL
, contour_plot
, aligned_y_hist
, ncol = 2
, nrow = 2
, rel_heights = c(0.2, 1)
, rel_widths = c(1, 0.2)
)
Run Code Online (Sandbox Code Playgroud)
您可以使用ggstatsplot使用边际直方图轻松创建有吸引力的散点图(它也可以拟合并描述模型):
data(iris)
library(ggstatsplot)
ggscatterstats(
data = iris,
x = Sepal.Length,
y = Sepal.Width,
xlab = "Sepal Length",
ylab = "Sepal Width",
marginal = TRUE,
marginal.type = "histogram",
centrality.para = "mean",
margins = "both",
title = "Relationship between Sepal Length and Sepal Width",
messages = FALSE
)
Run Code Online (Sandbox Code Playgroud)
或更具吸引力(默认情况下)ggpubr:
devtools::install_github("kassambara/ggpubr")
library(ggpubr)
ggscatterhist(
iris, x = "Sepal.Length", y = "Sepal.Width",
color = "Species", # comment out this and last line to remove the split by species
margin.plot = "histogram", # I'd suggest removing this line to get density plots
margin.params = list(fill = "Species", color = "black", size = 0.2)
)
Run Code Online (Sandbox Code Playgroud)
更新:
正如@aickley所建议的那样,我使用了开发版本来创建情节。
使用ggpubrand 的另一种解决方案cowplot,但在这里我们使用创建绘图cowplot::axis_canvas并将它们添加到原始绘图中cowplot::insert_xaxis_grob:
library(cowplot)
library(ggpubr)
# Create main plot
plot_main <- ggplot(faithful, aes(eruptions, waiting)) +
geom_point()
# Create marginal plots
# Use geom_density/histogram for whatever you plotted on x/y axis
plot_x <- axis_canvas(plot_main, axis = "x") +
geom_density(aes(eruptions), faithful)
plot_y <- axis_canvas(plot_main, axis = "y", coord_flip = TRUE) +
geom_density(aes(waiting), faithful) +
coord_flip()
# Combine all plots into one
plot_final <- insert_xaxis_grob(plot_main, plot_x, position = "top")
plot_final <- insert_yaxis_grob(plot_final, plot_y, position = "right")
ggdraw(plot_final)
Run Code Online (Sandbox Code Playgroud)