簡體   English   中英

R:找到最大密度 plot

[英]R: Find maximum of density plot

我有大約 25,000 行myData的數據,其中列attr的值從 0 -> 45,600。 我不確定如何制作簡化或可重現的數據...

無論如何,我正在繪制attr的密度,如下所示,我還找到了密度最大的attr值:

library(ggplot)
max <- which.max(density(myData$attr)$y)
density(myData$attr)$x[max]
ggplot(myData, aes(x=attr))+ 
  geom_density(color="darkblue", fill="lightblue")+
  geom_vline(xintercept = density(myData$attr)$x[max])+
  xlab("attr")

這是 plot 我在最大點處的 x 截距: 在此處輸入圖像描述

由於數據是傾斜的,因此我嘗試通過將scale_x_log10()添加到ggplot來以對數比例繪制 x 軸,這是新圖: 在此處輸入圖像描述

我現在的問題是:

1.為什么現在最高2分? 為什么我的 x 截距不再位於最大點?

2.如何找到 2 個新的最大點的截距?

最后,我嘗試將 y 軸轉換為count

ggplot(myData, aes(x=attr)) +
  stat_density(aes(y=..count..), color="black", fill="blue", alpha=0.3)+
  xlab("attr")+
  scale_x_log10()

我得到了以下 plot: 在此處輸入圖像描述

3.如何找到 2 個峰值的count

為什么密度形狀不同

為了讓我的評論更全面,ggplot 在進行密度估計之前先記錄日志,這會導致形狀差異,因為分箱覆蓋了域的不同部分。 例如,

(bins <- seq(1, 10, length.out = 10))
#>  [1]  1  2  3  4  5  6  7  8  9 10
(bins_log <- 10^seq(log10(1), log10(10), length.out = 10))
#>  [1]  1.000000  1.291550  1.668101  2.154435  2.782559  3.593814  4.641589
#>  [8]  5.994843  7.742637 10.000000

library(ggplot2)

ggplot(data.frame(x = c(bins, bins_log), 
                  trans = rep(c('identity', 'log10'), each = 10)), 
       aes(x, y = trans, col = trans)) + 
    geom_point()

偶數箱與日志箱

這種分箱會影響最終的密度形狀。 例如,比較未轉換的密度:

d <- density(mtcars$disp)
plot(d)

線性箱

到預先記錄的一個:

d_log <- density(log10(mtcars$disp))
plot(d_log)

在密度之前記錄

請注意,模式的高度會翻轉,我相信您要的是第一個,但是在密度之后應用了對數變換。 IE

d_x_log <- d
d_x_log$x <- log10(d_x_log$x)
plot(d_x_log)

原木前的密度

這里的模式是相似的,只是被壓縮了。

轉移到 ggplot

移至 ggplot 時,要在對數轉換之前進行密度估計,最簡單的方法是事先在 ggplot 之外進行:

library(ggplot2)

d <- density(mtcars$disp)

ggplot(data.frame(x = d$x, y = d$y), aes(x, y)) + 
    geom_density(stat = "identity", fill = 'burlywood', alpha = 0.3) + 
    scale_x_log10()

ggplot 在日志之前具有密度

尋找模式

當只有一個模式時找到模式相對容易; 它只是d$x[which.max(d$x)] 但是當您有多種模式時,這還不夠好,因為它只會顯示最高的模式。 一種解決方案是有效地求導並尋找斜率從正變為負的位置。 我們可以用diff以數字方式執行此操作,並且由於我們只關心結果是正數還是負數,因此在其上sign以將所有內容變為 -1 和 1。* 如果我們在that上調用diff ,除最大值外,所有內容都將為 0和最小值,分別為 -2 和 2。 然后我們可以查找which值小於 0,我們可以使用它來進行子集化。 (因為diff沒有在末尾插入NA ,所以您必須在索引中添加一個。)總而言之,設計用於密度 object,

d <- density(mtcars$disp)

modes <- function(d){
    i <- which(diff(sign(diff(d$y))) < 0) + 1
    data.frame(x = d$x[i], y = d$y[i])
}

modes(d)
#>          x           y
#> 1 128.3295 0.003100294
#> 2 305.3759 0.002204658

d$x[which.max(d$y)]    # double-check
#> [1] 128.3295

我們可以將它們添加到我們的 plot 中,它們會得到很好的轉換:

ggplot(data.frame(x = d$x, y = d$y), aes(x, y)) + 
    geom_density(stat = "identity", fill = 'mistyrose', alpha = 0.3) + 
    geom_vline(xintercept = modes(d)$x) +
    scale_x_log10()

使用模式線記錄 ggplot

繪制計數而不是密度

要將 y 軸轉換為計數而不是密度,請將 y 乘以觀察次數,觀察次數以n形式存儲在密度 object 中:

ggplot(data.frame(x = d$x, y = d$y * d$n), aes(x, y)) + 
    geom_density(stat = "identity", fill = 'thistle', alpha = 0.3) + 
    geom_vline(xintercept = modes(d)$x) +
    scale_x_log10()

記錄的ggplot計數密度

在這種情況下,它看起來有點傻,因為只有 32 個觀測值分布在一個寬域中,但是對於更大的 n 和更小的域,它更易於解釋:

d <- density(diamonds$carat, n = 2048)

ggplot(data.frame(x = d$x, y = d$y * d$n), aes(x, y)) + 
    geom_density(stat = "identity", fill = 'papayawhip', alpha = 0.3) + 
    geom_point(data = modes(d), aes(y = y * d$n)) +
    scale_x_log10()

鑽石計數密度圖


* 如果值正好為 0,則為 0,但這在這里不太可能並且無論如何都可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM