【问题标题】:Scatterplot with too many points点数过多的散点图
【发布时间】:2011-12-04 14:34:21
【问题描述】:

我正在尝试绘制 N=700K 的两个变量。问题是重叠太多,以至于情节主要变成了黑色的实心块。有没有办法得到一个灰度“云”,其中情节的黑暗是一个区域中点数的函数?换句话说,我希望绘图是一个“云”,而不是显示单个点,一个区域中的点数越多,该区域越暗。

【问题讨论】:

标签: r scatter-plot


【解决方案1】:

ggpointdensity package 中的geom_pointdenisty(最近由 Lukas Kremer 和 Simon Anders(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】:

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

    【讨论】:

    • 这是一个非常漂亮的答案,我认为值得更多的支持。
    • 给我一个错误 scale_fill_viridis_c() 中的错误:找不到函数“scale_fill_viridis_c”
    • 更新了 ggplot2,重新安装了 ggplot2 并重新加载了 ggplot2。没有修复错误。单独安装的 'viridis' 包,让我使用 'scale_fill_viridis' 函数,但不使用 'scale_fill_viridis_c' 函数,它仍然给出相同的错误
    • 哦,我相信你。那里没有问题。只是试图找出错误的根源。
    【解决方案3】:

    我最喜欢绘制此类数据的方法是this question 中描述的一种方法 - 散点密度图。这个想法是做一个散点图,但根据它们的密度(粗略地说,该区域的重叠量)对点进行着色。

    同时:

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

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

    【讨论】:

    • 这也是我最喜欢的方式。请参阅my answer 了解如何在R 中实现这一点。
    【解决方案4】:

    Alpha 混合也很容易与基本图形一起使用。

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

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

    【讨论】:

    • 只是为了添加一点上下文,“#000000”是黑色,添加到颜色末尾的“33”是不透明度---这里是33%。
    • 感谢您的补充说明。
    • 非常有意义。谢谢,亚伦和查理。
    • 小注;数字是十六进制的,所以 33 实际上是 3/16 不透明的。
    【解决方案5】:

    你也可以使用密度等高线(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")
    

    【讨论】:

      【解决方案6】:

      您还可以查看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])
      

      【讨论】:

      • 第二个情节很棒!
      • 如果我有 3D 数据怎么办?
      • @skan:你可以为此打开一个新问题。
      • 不幸的是,ggsubplot 包不再维护并从 cran repo 中删除...您知道可用于生成上述前两个图的替代包吗?
      • 如果你使用的是旧版本的R&ggplot2,你应该可以让它工作
      【解决方案7】:

      您可能会发现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 是我的首选解决方案 - 它可以获取大量点数,然后安全地创建绘图。我不确定其他人是否会尝试制作情节,而只是在事后以不同的方式着色。
      • 像 hexbin 这样的 3D 数据吗?
      【解决方案8】:

      解决此问题的一种方法是使用 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()
      

      【讨论】:

      • 如何更改颜色?我现在得到蓝色到黑色的刻度,而我想得到 reg,绿色的蓝色刻度。
      • @user1007742 使用scale_fill_gradient() 并指定您自己的低色和高色,或使用scale_fill_brewer() 并从连续调色板之一中进行选择。
      • @joran 谢谢,现在正在工作。如何改变点的类型/形状?我得到六边形或正方形。我只想要简单的点。当我使用 geom_point() 时,它给了我错误。
      • @user1007742 好吧,它被称为“六边形分箱”是有原因的! ;) 它不是在绘制“点”,而是将整个区域划分为六边形(或矩形)箱,然后根据该箱中有多少点简单地对箱进行着色。所以简短的回答是“你不能”。如果你想要不同的形状,你必须使用geom_point() 并绘制每个单独的点。
      • 如果我有 3D 数据怎么办?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 2021-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多