【问题标题】:Show only high density areas with ggplot2's stat_density_2d使用 ggplot2 的 stat_density_2d 仅显示高密度区域
【发布时间】:2018-01-16 14:00:15
【问题描述】:

我想将 stat_density2D 函数与分类变量一起使用,但将我的绘图限制在高密度区域,以减少重叠并提高易读性。

我们以以下数据为例:

plot_data <-
  data.frame(X = c(rnorm(300, 3, 2.5), rnorm(150, 7, 2)),
             Y = c(rnorm(300, 6, 2.5), rnorm(150, 2, 2)),
             Label = c(rep('A', 300), rep('B', 150)))

ggplot(plot_data, aes(X, Y, colour = Label)) + geom_point()

通过二维密度图,我们获得重叠密度

ggplot(plot_data, aes(X, Y)) + 
  stat_density_2d(geom = "polygon", aes(alpha = ..level.., fill = Label))

是否可以仅绘制高密度区域(例如level&gt;0.03)?我找到的唯一解决方案是“作弊”并手动修改 ..levels.. 变量,可以使用阶跃函数或任何幂变换,就像这个简单的示例一样。

ggplot(plot_data, aes(X, Y)) + 
  stat_density_2d(geom = "polygon", aes(alpha = (..level..) ^ 2, fill = Label)) + 
  scale_alpha_continuous(range = c(0, 1))

除了修改..levels.. 变量之外,是否可以要求 ggplot2/stat_density2D 函数仅关注特定范围的密度级别?我尝试使用scale_alpha_continuous 函数的rangelimits 参数,但没有任何相关结果...

谢谢!

【问题讨论】:

  • 您可以在scale_alpha_continuous中使用limits,并设置上下限。外面的一切都将被忽略(默认情况下)。
  • 请确保查看者能够理解绘制的区域不包含该组的所有数据。
  • 感谢您的回答,但我不确定这是否足够。我同意这是合乎逻辑的,但据我尝试它不起作用,请参阅ggplot(plot_data, aes(X,Y))+stat_density_2d(geom="polygon", aes(alpha=..level.., fill=Label)) + scale_alpha_continuous(limits=c(0.1,0.04))。顺便说一句你是对的,这种修改必须明确说明和解释

标签: r ggplot2


【解决方案1】:

选项 1
通过向stat_density_2d 添加参数bins,您绝对可以避免过度绘制、控制并以非常经济的方式将注意力吸引到一些密度区域。

set.seed(123)
plot_data <-
  data.frame(
    X = c(rnorm(300, 3, 2.5), rnorm(150, 7, 2)),
    Y = c(rnorm(300, 6, 2.5), rnorm(150, 2, 2)),
    Label = c(rep('A', 300), rep('B', 150))
  )
ggplot(plot_data, aes(X, Y, group = Label)) +
  stat_density_2d(geom = "polygon",
                  aes(alpha = ..level.., fill = Label),
                  bins = 4) 

选项 2
为我们不想绘制的那些级别手动分配颜色,NA。主要缺点是,我们应该事先知道(或计算它们)所需的级别和颜色的数量。在我的set.seed(123)示例中,我们需要 7。

ggplot(plot_data, aes(X, Y, group = Label)) +
  stat_density_2d(geom = "polygon", aes(fill = as.factor(..level..))) +
  scale_fill_manual(values = c(NA, NA, NA,"#BDD7E7", "#6BAED6", "#3182BD", "#08519C"))

【讨论】:

    【解决方案2】:

    您必须手动生成 2d 内核密度,然后绘制结果。这样,您可以选择每个点上的值,例如避免重叠。 代码如下:

    plot_data <-
      data.frame(X = c(rnorm(300, 3, 2.5), rnorm(150, 7, 2)),
                 Y = c(rnorm(300, 6, 2.5), rnorm(150, 2, 2)),
                 Label = c(rep('A', 300), rep('B', 150)))
    
    
    library(ggplot2)
    library(MASS)
    library(tidyr)
    #Calculate the range
    xlim <- range(plot_data$X)
    ylim <-range(plot_data$Y)
    
    
    #Genrate the kernel density for each group
    newplot_data <- plot_data %>% group_by(Label) %>% do(Dens=kde2d(.$X, .$Y, n=100, lims=c(xlim,ylim)))
    
    #Transform the density in  data.frame
    newplot_data  %<>%  do(Label=.$Label, V=expand.grid(.$Dens$x,.$Dens$y), Value=c(.$Dens$z)) %>% do(data.frame(Label=.$Label,x=.$V$Var1, y=.$V$Var2, Value=.$Value))
    
    #Untidy data and chose the value for each point.
    #In this case chose the value of the label with highest value  
       newplot_data  %<>%   spread( Label,value=Value) %>%
            mutate(Level = if_else(A>B, A, B), Label = if_else(A>B,"A", "B"))
    

    等高线图:

    # Contour plot
    ggplot(newplot_data, aes(x,y, z=Level, fill=Label, alpha=..level..))  + stat_contour(geom="polygon")
    

    由于圆形误差,等高线图似乎有一些重叠。我们可以试试光栅图:

    #Raster plot
    ggplot(newplot_data, aes(x,y, fill=Label, alpha=Level))  + geom_raster()
    

    【讨论】:

      猜你喜欢
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 2018-06-21
      • 2012-08-21
      • 2017-04-26
      • 1970-01-01
      • 2019-01-04
      • 1970-01-01
      相关资源
      最近更新 更多