散点图太多


126

我正在尝试绘制两个变量,其中N = 700K。问题是重叠太多,因此该图大部分变为黑色实心块。有什么办法可以使灰度图的暗度与区域中的点数成函数关系呢?换句话说,我不想显示单个点,而是希望该图成为一个“云”,一个区域中的点数越多,该区域越暗。


4
这听起来像你正在寻找一个热图: flowingdata.com/2010/01/21/...

Answers:


145

解决此问题的一种方法是使用Alpha混合,它使每个点都稍微透明。因此,区域显得更暗,上面绘制了更多点。

这很容易做到ggplot2

df <- data.frame(x = rnorm(5000),y=rnorm(5000))
ggplot(df,aes(x=x,y=y)) + geom_point(alpha = 0.3)

在此处输入图片说明

解决此问题的另一种简便方法是(可能更适合于您拥有的点数)是六角形装仓:

ggplot(df,aes(x=x,y=y)) + stat_binhex()

在此处输入图片说明

此外,还有常规的旧矩形装箱(省略了图像),更像是传统的热图:

ggplot(df,aes(x=x,y=y)) + geom_bin2d()

1
我该如何改变颜色?我现在正从蓝色变为黑色标度,而我想获得reg,绿色蓝色标度。
user1007742 2014年

@ user1007742使用scale_fill_gradient()并指定您自己的低色和高色,或者使用scale_fill_brewer()并从顺序调色板之一中进行选择。
joran 2014年

@joran谢谢,现在正在工作。如何更改点的类型/形状?我得到六角形或正方形。我只想要简单的点。当我使用geom_point()时,它给了我错误。
user1007742 2014年

1
@ user1007742好吧,由于某种原因,它被称为“六角合并”!;)并不是绘制“点”,而是将整个区域划分为六边形(或矩形)的容器,然后根据该容器中有多少个点简单地为容器着色。因此,简短的答案是“您不能”。如果需要不同的形状,则必须使用geom_point()并绘制每个点。
joran 2014年

如果我有3D数据怎么办?
skan

60

您也可以查看ggsubplot包装。该软件包实现了Hadley Wickham早在2011年(http://blog.revolutionanalytics.com/2011/10/ggplot2-for-big-data.html)提出的功能。

(下面,出于说明目的,我包括“点”层。)

library(ggplot2)
library(ggsubplot)

# Make up some data
set.seed(955)
dat <- data.frame(cond = rep(c("A", "B"), each=5000),
                  xvar = c(rep(1:20,250) + rnorm(5000,sd=5),rep(16:35,250) + rnorm(5000,sd=5)),
                  yvar = c(rep(1:20,250) + rnorm(5000,sd=5),rep(16:35,250) + rnorm(5000,sd=5)))


# Scatterplot with subplots (simple)
ggplot(dat, aes(x=xvar, y=yvar)) +
  geom_point(shape=1) +
  geom_subplot2d(aes(xvar, yvar,
                     subplot = geom_bar(aes(rep("dummy", length(xvar)), ..count..))), bins = c(15,15), ref = NULL, width = rel(0.8), ply.aes = FALSE)

在此处输入图片说明

但是,如果您要控制第三个变量,则此功能会很困难。

# Scatterplot with subplots (including a third variable) 

ggplot(dat, aes(x=xvar, y=yvar)) +
  geom_point(shape=1, aes(color = factor(cond))) +
  geom_subplot2d(aes(xvar, yvar,
                     subplot = geom_bar(aes(cond, ..count.., fill = cond))),
                 bins = c(15,15), ref = NULL, width = rel(0.8), ply.aes = FALSE)  

在此处输入图片说明

或者另一种方法是使用smoothScatter()

smoothScatter(dat[2:3])

在此处输入图片说明


3
第二个情节很棒!
里卡多·萨波特

如果我有3D数据怎么办?
skan

2
@ skan:您可以为此提出一个新问题。
majom '16

不幸的是,不再对ggsubplot软件包进行维护,并将其从cran仓库中删除了...您是否知道可用于生成类似于上述前两个图的替代软件包?
dieHellste,

如果您使用的是R&ggplot2的旧版本,则应该可以使其正常运行
-majom,

59

概述以下几个不错的选择ggplot2

library(ggplot2)
x <- rnorm(n = 10000)
y <- rnorm(n = 10000, sd=2) + x
df <- data.frame(x, y)

选项A:透明点

o1 <- ggplot(df, aes(x, y)) +
  geom_point(alpha = 0.05)

选项B:添加密度等高线

o2 <- ggplot(df, aes(x, y)) +
  geom_point(alpha = 0.05) +
  geom_density_2d()

选项C:添加填充的密度轮廓

o3 <- ggplot(df, aes(x, y)) +
  stat_density_2d(aes(fill = stat(level)), geom = 'polygon') +
  scale_fill_viridis_c(name = "density") +
  geom_point(shape = '.')

选项D:密度热图

o4 <- ggplot(df, aes(x, y)) +
  stat_density_2d(aes(fill = stat(density)), geom = 'raster', contour = FALSE) +       
  scale_fill_viridis_c() +
  coord_cartesian(expand = FALSE) +
  geom_point(shape = '.', col = 'white')

选项E:六边形

o5 <- ggplot(df, aes(x, y)) +
  geom_hex() +
  scale_fill_viridis_c() +
  geom_point(shape = '.', col = 'white')

选项F:地毯

o6 <- ggplot(df, aes(x, y)) +
  geom_point(alpha = 0.1) +
  geom_rug(alpha = 0.01)

合并成一个图:

cowplot::plot_grid(
  o1, o2, o3, o4, o5, o6,
  ncol = 2, labels = 'AUTO', align = 'v', axis = 'lr'
)

在此处输入图片说明


1
这是一个很好设计的答案,我认为值得更多投票。
Lalochezia,

给我一个错误scale_fill_viridis_c()中的错误:找不到函数“ scale_fill_viridis_c”
JustGettinStarted

更新了ggplot2,重新安装了ggplot2并重新加载了ggplot2。没有修复错误。单独安装的“ viridis”软件包,让我使用“ scale_fill_viridis”功能,但没有使用“ scale_fill_viridis_c”功能,该功能仍然会产生相同的错误
JustGettinStarted

哦,我相信你。那里没有问题。只是试图找到错误的根源。
JustGettin

51

基本图形也很容易进行Alpha混合。

df <- data.frame(x = rnorm(5000),y=rnorm(5000))
with(df, plot(x, y, col="#00000033"))

后面的前六个数字#是RGB十六进制的颜色,后两个数字是不透明度,再次是十六进制,所以33〜3 / 16th不透明。

在此处输入图片说明


20
只需添加一些上下文,“#000000”是黑色,添加到颜色末尾的“ 33”是不透明度-在这里是33%。
查理

感谢您的补充说明。
亚伦(Aaron)

很有道理。谢谢亚伦和查理。
user702432 2011年

12
次要音符;数字以十六进制表示,因此33实际上是3/16不透明。
亚伦(Aaron)

45

您还可以使用密度等高线(ggplot2):

df <- data.frame(x = rnorm(15000),y=rnorm(15000))
ggplot(df,aes(x=x,y=y)) + geom_point() + geom_density2d()

在此处输入图片说明

或将密度等高线与Alpha混合相结合:

ggplot(df,aes(x=x,y=y)) + 
    geom_point(colour="blue", alpha=0.2) + 
    geom_density2d(colour="black")

在此处输入图片说明


29

您可能会发现该hexbin软件包很有用。从的帮助页面hexbinplot

library(hexbin)
mixdata <- data.frame(x = c(rnorm(5000),rnorm(5000,4,1.5)),
                      y = c(rnorm(5000),rnorm(5000,2,3)),
                      a = gl(2, 5000))
hexbinplot(y ~ x | a, mixdata)

六边形图


+1 hexbin是我的首选解决方案-它可能需要占用大量点,然后安全地创建绘图。我不确定其他人是否会尝试绘制情节,而只是事后用不同的阴影来表示。
Iterator

像hexbin这样的3D数据?
skan

8

geom_pointdenistyggpointdensity可以让你在同一时间显现的密度和单个数据点(最近被卢卡斯克雷默和西蒙·安德斯(2019)开发的):

library(ggplot2)
# install.packages("ggpointdensity")
library(ggpointdensity)

df <- data.frame(x = rnorm(5000), y = rnorm(5000))
ggplot(df, aes(x=x, y=y)) + geom_pointdensity() + scale_color_viridis_c()


2

我最喜欢绘制这种类型数据的方法是此问题中描述的一种方法- 散布密度图。这个想法是做一个散点图,但要通过点的密度(大致来说,该区域的重叠量)来给点着色。

同时:

  • 清楚地显示异常值的位置,并且
  • 揭示了该图的密集区域中的任何结构。

这是链接问题的最高答案的结果:

散射密度图


1
这也是我最喜欢的方式。有关如何实现此目标的信息,请参见我的答案R
jan-glx
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.