提问



在R中,mean()median()是执行你期望的标准函数。mode()告诉你对象的内部存储模式,而不是它在参数中发生的最大值但是有没有标准的库函数来实现向量(或列表)的统计模式?

最佳参考


还有一个解决方案,适用于数字和数字字符/因子数据:


Mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}


在我的小机器上,可以生成&在大约半秒内找到10M整数向量的模式。

其它参考1


有一个包modeest,它提供单变量单峰(有时是多模)数据模式的估计量和通常概率分布模式的值。


mySamples <- c(19, 4, 5, 7, 29, 19, 29, 13, 25, 19)

library(modeest)
mlv(mySamples, method = "mfv")

Mode (most likely value): 19 
Bickel's modal skewness: -0.1 
Call: mlv.default(x = mySamples, method = "mfv")


有关更多信息,请参阅此页[53]

其它参考2


在r邮件列表上找到了这个,希望它有用。它也是我在想的。你会想要表格()数据,排序然后选择名字。它是hackish但应该工作。


names(sort(-table(x)))[1]

其它参考3


我发现肯·威廉姆斯在上面的帖子很棒,我添加了几行来解释NA值并使其变得容易。


Mode <- function(x, na.rm = FALSE) {
  if(na.rm){
    x = x[!is.na(x)]
  }

  ux <- unique(x)
  return(ux[which.max(tabulate(match(x, ux)))])
}

其它参考4


估计一个数字向量模式的快速而肮脏的方法,你认为它来自连续的单变量分布(例如正态分布),它定义并使用以下函数:


estimate_mode <- function(x) {
  d <- density(x)
  d$x[which.max(d$y)]
}


然后得到模式估计:


x <- c(5.8, 5.6, 6.2, 4.1, 4.9, 2.4, 3.9, 1.8, 5.7, 3.2)
estimate_mode(x)
## 5.439788

其它参考5


以下功能有三种形式:


method =mode[[default]]:计算单峰向量的模式,否则返回NA

method =nmodes:计算向量中的模式数量
method =modes:列出单峰或多峰矢量的所有模式


modeav <- function (x, method = "mode", na.rm = FALSE)
{
  x <- unlist(x)
  if (na.rm)
    x <- x[!is.na(x)]
  u <- unique(x)
  n <- length(u)
  #get frequencies of each of the unique values in the vector
  frequencies <- rep(0, n)
  for (i in seq_len(n)) {
    if (is.na(u[i])) {
      frequencies[i] <- sum(is.na(x))
    }
    else {
      frequencies[i] <- sum(x == u[i], na.rm = TRUE)
    }
  }
  #mode if a unimodal vector, else NA
  if (method == "mode" | is.na(method) | method == "")
  {return(ifelse(length(frequencies[frequencies==max(frequencies)])>1,NA,u[which.max(frequencies)]))}
  #number of modes
  if(method == "nmode" | method == "nmodes")
  {return(length(frequencies[frequencies==max(frequencies)]))}
  #list of all modes
  if (method == "modes" | method == "modevalues")
  {return(u[which(frequencies==max(frequencies), arr.ind = FALSE, useNames = FALSE)])}  
  #error trap the method
  warning("Warning: method not recognised.  Valid methods are 'mode' [default], 'nmodes' and 'modes'")
  return()
}

其它参考6


这里,另一个解决方案


freq <- tapply(mySamples,mySamples,length)
#or freq <- table(mySamples)
as.numeric(names(freq)[which.max(freq)])

其它参考7


我还不能投票,但RasmusBååth的答案正是我所寻求的。
但是,我会稍微修改一下,允许限制分布,例如仅在0和1之间的值。


estimate_mode <- function(x,from=min(x), to=max(x)) {
  d <- density(x, from=from, to=to)
  d$x[which.max(d$y)]
}


我们知道您可能不想限制所有发行版,然后从= - BIG NUMBER设置为=BIG NUMBER

其它参考8


我已经编写了以下代码以生成模式。


MODE <- function(dataframe){
    DF <- as.data.frame(dataframe)

    MODE2 <- function(x){      
        if (is.numeric(x) == FALSE){
            df <- as.data.frame(table(x))  
            df <- df[order(df$Freq), ]         
            m <- max(df$Freq)        
            MODE1 <- as.vector(as.character(subset(df, Freq == m)[, 1]))

            if (sum(df$Freq)/length(df$Freq)==1){
                warning("No Mode: Frequency of all values is 1", call. = FALSE)
            }else{
                return(MODE1)
            }

        }else{ 
            df <- as.data.frame(table(x))  
            df <- df[order(df$Freq), ]         
            m <- max(df$Freq)        
            MODE1 <- as.vector(as.numeric(as.character(subset(df, Freq == m)[, 1])))

            if (sum(df$Freq)/length(df$Freq)==1){
                warning("No Mode: Frequency of all values is 1", call. = FALSE)
            }else{
                return(MODE1)
            }
        }
    }

    return(as.vector(lapply(DF, MODE2)))
}


我们来试试吧:


MODE(mtcars)
MODE(CO2)
MODE(ToothGrowth)
MODE(InsectSprays)

其它参考9


这个hack应该可以正常工作。给你价值以及模式的数量:


Mode <- function(x){
a = table(x) # x is a vector
return(a[which.max(a)])
}

其它参考10


对Ken Williams的一个小修改回答,添加了可选参数na.rmreturn_multiple


与依赖names()的答案不同,此答案在返回值中维护x的数据类型。


stat_mode <- function(x, return_multiple = TRUE, na.rm = FALSE) {
  if(na.rm){
    x <- na.omit(x)
  }
  ux <- unique(x)
  freq <- tabulate(match(x, ux))
  mode_loc <- if(return_multiple) which(freq==max(freq)) else which.max(freq)
  return(ux[mode_loc])
}


要显示它与可选参数一起使用并维护数据类型:


foo <- c(2L, 2L, 3L, 4L, 4L, 5L, NA, NA)
bar <- c('mouse','mouse','dog','cat','cat','bird',NA,NA)

str(stat_mode(foo)) # int [1:3] 2 4 NA
str(stat_mode(bar)) # chr [1:3] "mouse" "cat" NA
str(stat_mode(bar, na.rm=T)) # chr [1:2] "mouse" "cat"
str(stat_mode(bar, return_mult=F, na.rm=T)) # chr "mouse"


感谢@Frank的简化。

其它参考11


基于@Chris的函数来计算模式或相关指标,然而使用Ken Williams的方法来计算频率。这个提供了对没有模式(所有元素同等频繁)的情况的修复,以及一些更易读的method名称。


Mode <- function(x, method = "one", na.rm = FALSE) {
  x <- unlist(x)
  if (na.rm) {
    x <- x[!is.na(x)]
  }

  # Get unique values
  ux <- unique(x)
  n <- length(ux)

  # Get frequencies of all unique values
  frequencies <- tabulate(match(x, ux))
  modes <- frequencies == max(frequencies)

  # Determine number of modes
  nmodes <- sum(modes)
  nmodes <- ifelse(nmodes==n, 0L, nmodes)

  if (method %in% c("one", "mode", "") | is.na(method)) {
    # Return NA if not exactly one mode, else return the mode
    if (nmodes != 1) {
      return(NA)
    } else {
      return(ux[which(modes)])
    }
  } else if (method %in% c("n", "nmodes")) {
    # Return the number of modes
    return(nmodes)
  } else if (method %in% c("all", "modes")) {
    # Return NA if no modes exist, else return all modes
    if (nmodes > 0) {
      return(ux[which(modes)])
    } else {
      return(NA)
    }
  }
  warning("Warning: method not recognised.  Valid methods are 'one'/'mode' [default], 'n'/'nmodes' and 'all'/'modes'")
}


由于它使用Ken的方法计算频率,性能也得到优化,使用AkselA的帖子我对之前的一些答案进行了基准测试,以显示我的函数在性能上与Ken的关系如何,以及各种输出的条件选项只会产生轻微的开销:
[54]

其它参考12


R有很多附加软件包,其中一些可能提供数字列表/系列/向量的[[统计]]模式。


然而,R本身的标准库似乎没有这样的内置方法!解决这个问题的一种方法是使用一些类似下面的结构(并且如果经常使用,则将其转换为函数...) :


mySamples <- c(19, 4, 5, 7, 29, 19, 29, 13, 25, 19)
tabSmpl<-tabulate(mySamples)
SmplMode<-which(tabSmpl== max(tabSmpl))
if(sum(tabSmpl == max(tabSmpl))>1) SmplMode<-NA
> SmplMode
[1] 19


对于更大的样本列表,应该考虑使用临时变量作为max(tabSmpl)值(我不知道R会自动优化这个)


参考:参见中位数和模式怎么样?在 KickStarting R课程

这似乎证实了(至少在撰写本课时)R中没有ta模式函数(正如你所发现的那样...模式()用于断言变量的类型)。[55]]]

其它参考13


这是一个找到模式的函数:


mode <- function(x) {
  unique_val <- unique(x)
  counts <- vector()
  for (i in 1:length(unique_val)) {
    counts[i] <- length(which(x==unique_val[i]))
  }
  position <- c(which(counts==max(counts)))
  if (mean(counts)==max(counts)) 
    mode_x <- 'Mode does not exist'
  else 
    mode_x <- unique_val[position]
  return(mode_x)
}

其它参考14


这很好用


> a<-c(1,1,2,2,3,3,4,4,5)
> names(table(a))[table(a)==max(table(a))]

其它参考15


虽然我喜欢肯威廉姆斯的简单功能,但我想检索多种模式(如果它们存在)。考虑到这一点,我使用以下函数返回模式列表,如果是多个或单个。


rmode <- function(x) {
  x <- sort(x)  
  u <- unique(x)
  y <- lapply(u, function(y) length(x[x==y]))
  u[which( unlist(y) == max(unlist(y)) )]
} 

其它参考16


我正在浏览所有这些选项并开始怀疑它们的相关特性和性能,所以我做了一些测试。如果其他人对此感到好奇,我会在这里分享我的结果。


我不想打扰这里发布的所有函数,我选择基于一些标准关注一个样本:函数应该对字符,因子,逻辑和数字向量起作用,它应该适当地处理NA和其他有问题的值,并且输出应该是明智的,即没有数字作为字符或其他这样的愚蠢。


我还添加了一个我自己的功能,它基于与chrispy相同的rle想法,除了适用于更一般的用途:


library(magrittr)

Aksel <- function(x, freq=FALSE) {
    z <- 2
    if (freq) z <- 1:2
    run <- x %>% as.vector %>% sort %>% rle %>% unclass %>% data.frame
    colnames(run) <- c("freq", "value")
    run[which(run$freq==max(run$freq)), z] %>% as.vector   
}

set.seed(2)

F <- sample(c("yes", "no", "maybe", NA), 10, replace=TRUE) %>% factor
Aksel(F)

# [1] maybe yes  

C <- sample(c("Steve", "Jane", "Jonas", "Petra"), 20, replace=TRUE)
Aksel(C, freq=TRUE)

# freq value
#    7 Steve


我最终通过microbenchmark在两组测试数据上运行了五个函数。函数名称指其各自的作者:


[56]


Chris函数默认设置为method="modes"na.rm=TRUE以使其更具可比性,但除此之外,其作者使用的函数也是如此。


仅凭速度问题,Kens版本可以轻松获胜,但它也是唯一一个只报告一种模式的模式,无论有多少模式。通常情况下,在速度和多功能性之间需要权衡。在method="mode"中,如果有一种模式,Chris版本将返回一个值,否则为NA。我认为这是一个很好的接触。
我也觉得有趣的是,一些函数如何受到增加的独特值的影响,而其他函数几乎没有那么多。我没有详细研究代码来弄清楚为什么会这样,除了消除逻辑/数字作为原因。

其它参考17


为此提供了多种解决方案。我检查了第一个,然后写了我自己的。如果它可以帮助任何人发布在这里:


Mode <- function(x){
  y <- data.frame(table(x))
  y[y$Freq == max(y$Freq),1]
}


让我们举几个例子来测试它。我正在采用iris数据集。让我们用数字数据进行测试


> Mode(iris$Sepal.Length)
[1] 5


您可以验证是否正确。


现在,虹膜数据集(物种)中唯一的非数字字段没有模式。让我们用我们自己的例子来测试


> test <- c("red","red","green","blue","red")
> Mode(test)
[1] red


修改



如评论中所述,用户可能希望保留输入类型。在这种情况下,模式功能可以修改为:


Mode <- function(x){
  y <- data.frame(table(x))
  z <- y[y$Freq == max(y$Freq),1]
  as(as.character(z),class(x))
}


函数的最后一行只是将最终模式值强制转换为原始输入的类型。

其它参考18


给出按频率排序的所有值的另一个简单选项是使用rle:


df = as.data.frame(unclass(rle(sort(mySamples))))
df = df[order(-df$lengths),]
head(df)

其它参考19


我会使用density()函数来识别(可能是连续的)分布的平滑最大值:


function(x) density(x, 2)$x[density(x, 2)$y == max(density(x, 2)$y)]


其中x是数据集合。注意调节平滑的密度函数的调整参数。

其它参考20


另一种可能的方案


Mode <- function(x) {
    if (is.numeric(x)) {
        x_table <- table(x)
        return(as.numeric(names(x_table)[which.max(x_table)]))
    }
}


用法:


set.seed(100)
v <- sample(x = 1:100, size = 1000000, replace = TRUE)
system.time(Mode(v))


输出:


   user  system elapsed 
   0.32    0.00    0.31 

其它参考21


对不起,我可能会把它看得太简单,但这不能做到这一点吗?(我的机器上的1E6值为1.3秒):


t0 <- Sys.time()
summary(as.factor(round(rnorm(1e6), 2)))[1]
Sys.time()-t0


你只需要用你的向量替换round(rnorm(1e6),2)。

其它参考22


您还可以计算实例在集合中发生的次数并找到最大数量。例如


> temp <- table(as.vector(x))
> names (temp)[temp==max(temp)]
[1] "1"
> as.data.frame(table(x))
r5050 Freq
1     0   13
2     1   15
3     2    6
> 

其它参考23


可以尝试以下功能:



  1. 将数值转换为因子
  2. 使用summary()获取频率表
  3. 返回模式频率最大的索引
  4. 转换因子返回数值即使有多于1种模式,此功能也能正常工作!


mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}

其它参考24


计算模式主要是因子变量然后我们可以使用


labels(table(HouseVotes84$V1)[as.numeric(labels(max(table(HouseVotes84$V1))))])


HouseVotes84是mlbench包中的数据集。


它会给出最大标签价值。内置函数本身更容易使用而无需编写函数。

其它参考25


下面是可用于在R中查找向量变量模式的代码。


a <- table([vector])

names(a[a==max(a)])

其它参考26


这是我的版本,包括分数。必须说你们这里给了我这么多简单明了的新解决方案。非常感谢!


get_mode <- function(v) {

  mode <- table(v) %>% 
    as_data_frame() %>% 
    mutate(frac = n/sum(n)) %>% 
    filter(n == max(n))

  return(list("mode_var" = mode$v,
              "n" = mode$n,
              "var_frac" = mode$frac))
}

get_mode(c(1,1,1,1,1,1,1,1,1,2,2,2,22,2,2,2,2,3234,3,4,545,343,56,676,76,764565,67,676,69,879,8978,9784,765,342,5236,43756,76,6,546))
$mode_var
[1] "1"

$n
[1] 9

$var_frac
[1] 0.2307692

其它参考27


计算包含离散值的向量v的MODE的简单方法是:


names(sort(table(v)))[length(sort(table(v)))]