计算R中多模态分布中的模式

时间:2014-12-11 08:35:14

标签: r distribution

我测量了所有孩子的身高。当我沿长度轴绘制所有高度时,结果如下:

enter image description here

每个红色(男孩)或紫色(女孩)蜱是一个孩子。如果两个孩子的身高相同(以毫米为单位),则蜱虫会堆叠起来。目前有七个孩子身高相同。 (蜱的高度和宽度没有意义。它们已被缩放为可见。)

如您所见,不同的高度沿轴线不均匀分布,而是围绕某些值聚集。

数据的组织图和密度图看起来像这样(在this answer之后绘制了两个密度估计值):

enter image description here

如您所见,这是一种多模态分发。

如何计算模式(在R中)?


以下是您可以使用的原始数据:

mm <- c(418, 527, 540, 553, 554, 558, 613, 630, 634, 636, 645, 648, 708, 714, 715, 725, 806, 807, 822, 823, 836, 837, 855, 903, 908, 910, 911, 913, 915, 923, 935, 945, 955, 957, 958, 1003, 1006, 1015, 1021, 1021, 1022, 1034, 1043, 1048, 1051, 1054, 1058, 1100, 1102, 1103, 1117, 1125, 1134, 1138, 1145, 1146, 1150, 1152, 1210, 1211, 1213, 1223, 1226, 1334)

2 个答案:

答案 0 :(得分:4)

我使用你的mm数据自己构建了一些东西。

首先让我们绘制mm的密度,以便可视化模式:

plot(density(mm))

enter image description here

因此,我们可以看到此分布中有两种模式。一个在600左右,一个在1000左右。让我们看看如何找到它们。

为了找到模式索引我做了这个功能:

find_modes<- function(x) {
  modes <- NULL
  for ( i in 2:(length(x)-1) ){
    if ( (x[i] > x[i-1]) & (x[i] > x[i+1]) ) {
      modes <- c(modes,i)
    }
  }
  if ( length(modes) == 0 ) {
    modes = 'This is a monotonic distribution'
  }
  return(modes)
}

让我们试试密度:

mymodes_indices <- find_modes(density(mm)$y) #you need to try it on the y axis

现在mymodes_indices包含我们模式的索引,即:

> density(mm)$y[mymodes_indices]  #just to confirm that those are the correct
[1] 0.0008946929 0.0017766183

> density(mm)$x[mymodes_indices] #the actual modes
[1]  660.2941 1024.9067

希望它有所帮助!

答案 1 :(得分:2)

我修改了Jeffrey EvansPeak of the kernel density estimation的答案,允许修改bw参数,从而获得更多或更少的峰值。对于其他情况,这将是必要的,这将产生许多峰值与接受的答案。参数signifi允许处理关系。

library(dplyr)
library(tidyr)
get.modes2 <- function(x,adjust,signifi,from,to) {  
  den <- density(x, kernel=c("gaussian"),adjust=adjust,from=from,to=to)
  den.s <- smooth.spline(den$x, den$y, all.knots=TRUE, spar=0.1)
  s.1 <- predict(den.s, den.s$x, deriv=1)
  s.0 <- predict(den.s, den.s$x, deriv=0)
  den.sign <- sign(s.1$y)
  a<-c(1,1+which(diff(den.sign)!=0))
  b<-rle(den.sign)$values
  df<-data.frame(a,b)
  df = df[which(df$b %in% -1),]
  modes<-s.1$x[df$a]
  density<-s.0$y[df$a]
  df2<-data.frame(modes,density)
  df2$sig<-signif(df2$density,signifi)
  df2<-df2[with(df2, order(-sig)), ] 
  #print(df2)
  df<-as.data.frame(df2 %>% 
                      mutate(m = min_rank(desc(sig)) ) %>% #, count = sum(n)) %>% 
                      group_by(m) %>% 
                      summarize(a = paste(format(round(modes,2),nsmall=2), collapse = ',')) %>%
                      spread(m, a, sep = ''))
  colnames(df)<-paste0("m",1:length(colnames(df)))
  print(df)
}
mm <- c(418, 527, 540, 553, 554, 558, 613, 630, 634, 636, 645, 648, 708, 714, 715, 725, 806, 807, 822, 823, 836, 837, 855, 903, 908, 910, 911, 913, 915, 923, 935, 945, 955, 957, 958, 1003, 1006, 1015, 1021, 1021, 1022, 1034, 1043, 1048, 1051, 1054, 1058, 1100, 1102, 1103, 1117, 1125, 1134, 1138, 1145, 1146, 1150, 1152, 1210, 1211, 1213, 1223, 1226, 1334)
mmdf<-data.frame(mm=mm)
library(ggplot2)
#0.25 defines the number of peaks.
ggplot(mmdf,aes(mm)) + geom_density(adjust=0.25) + xlim((min(mm)-1),(max(mm)+1) )
#2 defines ties
modes<-get.modes2(mm,adjust=0.25,2,min(mm)-1,max(mm)+1)
#       m1     m2      m3            m4      m5     m6     m7              m8
#1 1031.40 921.81 1133.79 636.17,826.60 1216.43 548.14 715.22  418.80,1335.00

enter image description here