【问题标题】:How to find the statistical mode?如何找到统计模式?
【发布时间】:2022-01-22 04:43:19
【问题描述】:

在 R 中,mean()median() 是标准函数,可以满足您的期望。 mode() 告诉你对象的内部存储模式,而不是在其参数中出现最多的值。但是有没有一个标准的库函数可以实现向量(或列表)的统计模式?

【问题讨论】:

  • 您需要明确您的数据是整数、数字、因子...?数值的模式估计会有所不同,并使用间隔。见modeest
  • 为什么 R 没有内置的 mode 函数?为什么 R 认为 mode 与函数 class 相同?

标签: r statistics r-faq


【解决方案1】:

在 r 邮件列表中找到此内容,希望对您有所帮助。反正我也是这么想的。您需要 table() 数据,排序然后选择名字。这很 hackish,但应该可以工作。

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

【讨论】:

  • 这也是一个巧妙的解决方法。它有一些缺点:排序算法可能比基于 max() 的方法更耗费空间和时间(=> 对于更大的样本列表要避免)。输出也是模式(请原谅双关语/歧义)“字符”而不是“数字”。当然,测试多模态分布的需要通常需要存储已排序的表以避免重新处理它。
  • 我用 1e6 个元素测量了运行时间,这个解决方案比接受的答案快了几乎 3 个元素!
  • 我只是使用 as.numeric() 将其转换为数字。工作得很好。谢谢!
  • 这个解决方案的问题是在有多个模式的情况下它是不正确的。
【解决方案2】:

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 lesson
这似乎证实了(至少在撰写本课时)R 中没有模式函数(嗯...... mode() 正如你所发现的那样用于断言变量的类型)。

【讨论】:

    【解决方案3】:

    有包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")
    

    欲了解更多信息,请参阅this page

    【讨论】:

    • 所以要获取模式值,mfv(mySamples)[1]1 很重要,因为它实际上返回最频繁的值s
    • 它在这个例子中似乎不起作用: library(modeest) a
    • @atomicules: 使用 [1] 你只能得到第一种模式。对于双峰或一般 n 模态分布,您只需要 mfv(mySamples)
    • 对于 R 版本 3.6.0,当我尝试 mfv(mysamples) 时,它说函数“找不到函数“mlv”和同样的错误。折旧了吗?
    • @DrNishaArora:你下载了“modeest”包吗?
    【解决方案4】:

    这里,另一种解决方案:

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

    【讨论】:

    • 可以将第一行替换成表格。
    • 我在想 'tapply' 比 'table' 更有效,但它们都使用了 for 循环。我认为与 table 的解决方案是等效的。我更新了答案。
    【解决方案5】:

    为了生成模式,我编写了以下代码。

    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)
    

    【讨论】:

      【解决方案6】:

      另一种解决方案,适用于数字和字符/因子数据:

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

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

      如果您的数据集可能有多种模式,上述解决方案采用与which.max 相同的方法,并返回模式集的first-appearing 值。要返回 all 模式,请使用此变体(来自 cmets 中的 @digEmAll):

      Modes <- function(x) {
        ux <- unique(x)
        tab <- tabulate(match(x, ux))
        ux[tab == max(tab)]
      }
      

      【讨论】:

      • 也适用于逻辑!为所有类型的向量保留数据类型(与其他答案中的某些实现不同)。
      • 这不会返回多模式数据集的所有模式(例如c(1,1,2,2))。您应该将最后一行更改为:tab &lt;- tabulate(match(x, ux)); ux[tab == max(tab)]
      • @verybadatthis 为此,您只需将ux[which.max(tabulate(match(x, ux)))] 替换为max(tabulate(match(x, ux)))
      • 您注意到Mode(1:3) 给出了1Mode(3:1) 给出了3,所以如果它们都是唯一的,Mode 返回最频繁的元素或第一个。
      • 正如恩里克所说:当没有模式时,这会失败,而是给你的印象是 first 值是模式。如果在这些情况下返回 0NA 会好得多。
      【解决方案7】:

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

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

      【讨论】:

        【解决方案8】:

        估计您认为来自连续单变量分布(例如正态分布)的数字向量的众数的一种快速而肮脏的方法是定义和使用以下函数:

        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
        

        【讨论】:

        • 请注意这一点:您可以通过这种方式获得任何一组连续数字的“模式”。数据不需要来自正态分布即可工作。这是一个从均匀分布中获取数字的示例。 set.seed(1); a&lt;-runif(100); mode&lt;-density(a)$x[which.max(density(a)$y)]; abline(v=mode)
        • error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
        • @xhie 该错误消息告诉您您需要知道的一切。如果您只有一点,则需要在调用density 时手动设置带宽。但是,如果您只有一个数据点,那么该数据点的值可能是您对该模式的最佳猜测......
        • 你是对的,但我只添加了一个调整:estimate_mode &lt;- function(x) { if (length(x)&gt;1){ d &lt;- density(x) d$x[which.max(d$y)] }else{ x } } 我正在测试估计主要方向风的方法,而不是使用带有圆形包的矢量平均值来估计方向的平均值。 I',使用多边形等级上的点,所以,有时只有一个点有方向。谢谢!
        • @xhie 听起来很合理:)
        【解决方案9】:

        以下函数有三种形式:

        method = "mode" [默认]:计算单峰向量的模式,否则返回 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()
        }
        

        【讨论】:

        • 在你对这个函数的描述中你交换了“modes”和“nmodes”。查看代码。实际上,“nmodes”返回值向量,“modes”返回模式数。尽管如此,你的功能是我迄今为止所见过的寻找模式的最佳选择。
        • 非常感谢您的评论。 “nmode”和“modes”现在应该按预期运行。
        • 您的函数几乎可以工作,除非每个值使用method = 'modes' 出现的频率相同。然后该函数返回所有唯一值,但实际上没有模式,因此它应该返回NA。我将添加另一个包含稍微优化版本的函数的答案,感谢您的启发!
        • 只有在对多模态向量使用默认方法时,非空数值向量通常应该使用此函数生成 NA。一个简单的数字序列(例如 1、2、3、4)的模式实际上是序列中的所有这些数字,因此对于类似的序列,“模式”的行为符合预期。例如modeave(c(1,2,3,4), method = "modes") 返回 [1] 1 2 3 4 不管怎样,我很想看到优化的函数,因为它在当前的资源相当密集状态
        • 有关此功能的更高效版本,请参阅上面@hugovdberg 的帖子 :)
        【解决方案10】:

        抱歉,我可能把它想得太简单了,但这不是工作吗? (我机器上的 1E6 值需要 1.3 秒):

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

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

        【讨论】:

        • 看看summary.factor——所有这些都是在其他答案中包装sort(table(...))方法。
        【解决方案11】:

        我还不能投票,但 Rasmus Båå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)]
        }
        

        我们知道您可能不想限制所有分布,然后设置 from=-"BIG NUMBER", to="BIG NUMBER"

        【讨论】:

        • error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
        • x 应该是一个向量
        【解决方案12】:

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

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

        【讨论】:

          【解决方案13】:

          这很好用

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

          【讨论】:

            【解决方案14】:

            可以试试下面的功能:

            1. 将数值转换为因子
            2. 使用summary()获取频率表
            3. return mode 频率最大的索引
            4. 即使有1个以上的模式,也可以将因子转换回数字,这个功能很好用!
            mode <- function(x){
              y <- as.factor(x)
              freq <- summary(y)
              mode <- names(freq)[freq[names(freq)] == max(freq)]
              as.numeric(mode)
            }
            

            【讨论】:

              【解决方案15】:

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

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

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

              【讨论】:

                【解决方案16】:

                我发现上面的 Ken Williams 帖子很棒,我添加了几行来说明 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)))])
                }
                

                【讨论】:

                • 我发现了一些加速方法,请参阅下面的答案。
                【解决方案17】:

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

                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)) )]
                } 
                

                【讨论】:

                • 如果它总是返回一个列表,那么对于编程使用会更加一致——如果只有一种模式,则长度为 1
                • 这是一个有效的观点@antoine-sac。我喜欢这个解决方案的地方是返回的向量使答案易于寻址。简单地处理函数的输出:r
                • 确切地说,这是您的解决方案的不足之处。如果mode 返回一个包含多个值的列表,则 r[1] 不是第一个值;相反,它是一个包含第一个值的长度为 1 的列表,您必须执行 r[[1]] 才能将第一个模式作为数字而不是列表。现在,当存在单一模式时,您的 r 不是列表,因此 r[1] 可以工作,这就是我认为它不一致的原因。但是由于 r[[1]] 在 r 是一个简单向量时也可以工作,因此实际上存在我没有意识到的一致性,因为您始终可以使用 [[ 来访问元素。
                【解决方案18】:

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

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

                【讨论】:

                  【解决方案19】:

                  另一种可能的解决方案:

                  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 
                  

                  【讨论】:

                    【解决方案20】:

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

                    不想打扰这里发布的所有函数,我选择关注基于几个标准的示例:该函数应该适用于字符、因子、逻辑和数字向量,它应该处理 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 在两组测试数据上运行了五个函数。函数名称参考各自的作者:

                    Chris 的函数默认设置为 method="modes"na.rm=TRUE 以使其更具可比性,但除此之外,这些函数由其作者在此处提供。

                    仅在速度方面,Kens 版本轻松获胜,但它也是其中唯一一款只会报告一种模式的版本,无论实际有多少。通常情况下,需要在速度和多功能性之间进行权衡。在method="mode" 中,如果存在一种模式,则 Chris 的版​​本将返回一个值,否则返回 NA。我认为这是一个很好的接触。 我还认为有趣的是,一些函数如何受到唯一值数量增加的影响,而其他函数则几乎没有。除了消除逻辑/数字作为原因之外,我还没有详细研究代码以找出原因。

                    【讨论】:

                    • 我喜欢你包含用于基准测试的代码,但对 20 个值进行基准测试毫无意义。我建议至少运行几十万条记录。
                    【解决方案21】:

                    基于@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 的性能,各种输出选项的条件仅导致次要开销:

                    【讨论】:

                    • 您提供的代码似乎或多或少是Mode 函数在pracma 包中的直接副本。需要解释一下吗?
                    • 真的吗?显然我不是唯一一个认为这是计算模式的好方法的人,但老实说我不知道​​(之前从不知道那个包)。我清理了 Chris 的功能,并利用 Ken 的版本对其进行了改进,如果它类似于其他人的代码纯属巧合。
                    • 我刚才查了一下,你指的是哪个版本的pracma包?据我所知,1.9.3 版的实现完全不同。
                    • 对函数进行了很好的修改。在进一步阅读之后,我得出的结论是,对于均匀分布或单频分布是否有节点没有共识,一些消息来源说模式列表是分布本身,其他人说没有节点。唯一的共识是,为此类分布生成一个模式列表既不是很有信息量,也不是特别有意义。如果您希望上述函数产生这种情况下的模式,则删除以下行:nmodes
                    • @greendiod 抱歉,我错过了您的评论。可通过以下要点获得:gist.github.com/Hugovdberg/0f00444d46efd99ed27bbe227bdc4d37
                    【解决方案22】:

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

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

                    【讨论】:

                      【解决方案23】:

                      这个 hack 应该可以正常工作。为您提供模式的值和计数:

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

                      【讨论】:

                        【解决方案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】:

                            对 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 的简化。

                            【讨论】:

                              【解决方案27】:

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

                              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
                              

                              编辑

                              如 cmets 中所述,用户可能希望保留输入类型。这种情况下mode函数可以修改为:

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

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

                              【讨论】:

                              • 这会返回一个因子,而用户可能希望保留输入的类型。也许添加一个中间步骤y[,1] &lt;- sort(unique(x))
                              【解决方案28】:

                              模式并非在所有情况下都有用。所以函数应该解决这种情况。试试下面的函数。

                              Mode <- function(v) {
                                # checking unique numbers in the input
                                uniqv <- unique(v)
                                # frquency of most occured value in the input data
                                m1 <- max(tabulate(match(v, uniqv)))
                                n <- length(tabulate(match(v, uniqv)))
                                # if all elements are same
                                same_val_check <- all(diff(v) == 0)
                                if(same_val_check == F){
                                  # frquency of second most occured value in the input data
                                  m2 <- sort(tabulate(match(v, uniqv)),partial=n-1)[n-1]
                                  if (m1 != m2) {
                                    # Returning the most repeated value
                                    mode <- uniqv[which.max(tabulate(match(v, uniqv)))]
                                  } else{
                                    mode <- "Two or more values have same frequency. So mode can't be calculated."
                                  }
                                } else {
                                  # if all elements are same
                                  mode <- unique(v)
                                }
                                return(mode)
                              }
                              

                              输出,

                              x1 <- c(1,2,3,3,3,4,5)
                              Mode(x1)
                              # [1] 3
                              
                              x2 <- c(1,2,3,4,5)
                              Mode(x2)
                              # [1] "Two or more varibles have same frequency. So mode can't be calculated."
                              
                              x3 <- c(1,1,2,3,3,4,5)
                              Mode(x3)
                              # [1] "Two or more values have same frequency. So mode can't be calculated."
                              

                              【讨论】:

                              • 对不起,我只是不明白这如何为已发布的内容添加任何新内容。此外,您的输出似乎与您上面的功能不一致。
                              • 以编程方式返回带有消息的字符串没有用处。如果输入不合适,请使用 stop() 表示没有结果的错误,或者使用 warning()/message()NA 结果。
                              【解决方案29】:

                              这建立在 jprockbelly 的答案之上,为非常短的向量添加了加速。这在将模式应用于具有大量小组的 data.frame 或数据表时很有用:

                              Mode <- function(x) {
                                 if ( length(x) <= 2 ) return(x[1])
                                 if ( anyNA(x) ) x = x[!is.na(x)]
                                 ux <- unique(x)
                                 ux[which.max(tabulate(match(x, ux)))]
                              }
                              

                              【讨论】:

                                【解决方案30】:

                                我认为您的观察结果是来自 Real numbers,当您的观察结果为 2、2、3 和 3 时,您希望 mode 为 2.5,然后您可以用mode = l1 + i * (f1-f0) / (2f1 - f0 - f2)估计模式,其中l1..最频繁类的下限,f1..最频繁类的频率,f0 ..最频繁类之前的类频率,f2..最频繁类之后的类频率和 i..给定的类间隔,例如在123

                                #Small Example
                                x <- c(2,2,3,3) #Observations
                                i <- 1          #Class interval
                                
                                z <- hist(x, breaks = seq(min(x)-1.5*i, max(x)+1.5*i, i), plot=F) #Calculate frequency of classes
                                mf <- which.max(z$counts)   #index of most frequent class
                                zc <- z$counts
                                z$breaks[mf] + i * (zc[mf] - zc[mf-1]) / (2*zc[mf] - zc[mf-1] - zc[mf+1])  #gives you the mode of 2.5
                                
                                
                                #Larger Example
                                set.seed(0)
                                i <- 5          #Class interval
                                x <- round(rnorm(100,mean=100,sd=10)/i)*i #Observations
                                
                                z <- hist(x, breaks = seq(min(x)-1.5*i, max(x)+1.5*i, i), plot=F)
                                mf <- which.max(z$counts)
                                zc <- z$counts
                                z$breaks[mf] + i * (zc[mf] - zc[mf-1]) / (2*zc[mf] - zc[mf-1] - zc[mf+1])  #gives you the mode of 99.5
                                

                                如果您想要most frequent level 并且您有多个最频繁的级别,您可以获得所有级别,例如与:

                                x <- c(2,2,3,5,5)
                                names(which(max(table(x))==table(x)))
                                #"2" "5"
                                

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2010-10-05
                                  • 2011-12-15
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2013-09-15
                                  相关资源
                                  最近更新 更多