Existe uma função interna para encontrar o modo?

392

Em R, mean()e median()são funções padrão que fazem o que você esperaria. mode()informa o modo de armazenamento interno do objeto, não o valor que ocorre mais em seu argumento. Mas existe uma função de biblioteca padrão que implementa o modo estatístico para um vetor (ou lista)?

usuario
fonte
4
Você precisa esclarecer se seus dados são inteiros, numéricos, fator ...? A estimativa de modo para numéricos será diferente e usa intervalos. Veja modeest
smci
2
Por que o R não possui uma função interna para o modo? Por que R considera modeo mesmo que a função class?
Corey Levinson

Respostas:

400

Mais uma solução, que funciona para dados numéricos e de caracteres / fator:

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

Na minha pequena máquina, isso pode gerar e encontrar o modo de um vetor inteiro de 10M em cerca de meio segundo.

Se seu conjunto de dados pode ter vários modos, a solução acima adota a mesma abordagem que which.maxe retorna o primeiro valor que aparece no conjunto de modos. Para retornar todos os modos, use esta variante (de @digEmAll nos comentários):

Modes <- function(x) {
  ux <- unique(x)
  tab <- tabulate(match(x, ux))
  ux[tab == max(tab)]
}
Ken Williams
fonte
7
Também funciona para lógicas! Preserva o tipo de dados para todos os tipos de vetores (diferente de algumas implementações em outras respostas).
DavidC
39
Isso não retorna todos os modos no caso de um conjunto de dados multimodal (por exemplo c(1,1,2,2)). Você deve alterar sua última linha com:tab <- tabulate(match(x, ux)); ux[tab == max(tab)]
digEmAll
6
@verybadatthis Por isso, você substituiria ux[which.max(tabulate(match(x, ux)))]por apenas max(tabulate(match(x, ux))).
Ken Williams
4
Você nota que Mode(1:3)1e Mode(3:1)3, portanto o Mode retorna o elemento mais frequente ou o primeiro, se todos eles forem únicos.
Enrique Pérez Herrero
2
Como Enrique disse: Isso falha quando não há modo e, em vez disso, dá a impressão de que o primeiro valor é o modo. Teria sido muito melhor se ele retornasse 0ou NAnesses casos.
Not2qubit 11/0918
66

Existe um pacote modeestque fornece estimadores do modo de dados unimodais unimodais (e às vezes multimodais) e valores dos modos de distribuições usuais de probabilidade.

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

Para mais informações, consulte esta página

George Dontas
fonte
7
Então, apenas para obter o valor do modo mfv(mySamples)[1],. O 1ser importante, na verdade, retorna os valores mais frequentes s .
Atomicules
parece não funcionar neste exemplo: library (modeest) a <- rnorm (50, 30, 2) b <- rnorm (100, 35, 2) c <- rnorm (20, 37, 2) temperaturaºC <- c (a, b, c) hist (temperaturaºC) #mean abline (v = média (temperaturaºC), col = "vermelho", lwd = 2) #medline abline (v = mediana (temperaturaºC), col = "preto", lwd = 2) #mode abline (v = mlv (temperaturaºC, método = "mfv") [1], col = "laranja", lwd = 2)
Agus camacho
11
@atomicules: com [1] você obtém apenas o primeiro modo. Para a distribuição bimodal ou geral n-modal você precisaria apenasmfv(mySamples)
Petzi
11
Para o R versão 3.6.0, diz que a função 'não pôde encontrar a função "mlv"' e o mesmo erro quando tentei mfv (mysamples). É depreciado?
Dr Nisha Arora
@DrNishaArora: Você baixou o pacote 'modeest'?
petzi
59

encontrou isso na lista de discussão r, espero que seja útil. É também o que eu estava pensando de qualquer maneira. Você deseja tabular () os dados, classificar e escolher o primeiro nome. É um truque, mas deve funcionar.

names(sort(-table(x)))[1]
Dan
fonte
6
Esse é um trabalho inteligente também. Ele tem algumas desvantagens: o algoritmo de classificação pode consumir mais espaço e tempo do que as abordagens baseadas em max () (=> a serem evitadas para listas de amostras maiores). Também a saída é do modo (perdoe o trocadilho / ambiguidade) "caractere" não "numérico". E, é claro, a necessidade de testar a distribuição multimodal normalmente exigiria o armazenamento da tabela classificada para evitar triturá-la novamente.
Mjv 30/03/10
2
Eu medi o tempo de execução com um fator de 1e6 elementos e essa solução foi mais rápida que a resposta aceita por quase o fator 3!
vonjd
Acabei de convertê-lo em número usando as.numeric (). Funciona perfeitamente bem. Obrigado!
Abhishek Singh
47

Achei o post de Ken Williams acima ótimo, adicionei algumas linhas para explicar os valores de NA e o tornei uma função para facilitar.

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)))])
}
jprockbelly
fonte
Encontrei algumas acelerações para isso, veja a resposta abaixo.
11558 Dan Houghton #
33

Uma maneira rápida e suja de estimar o modo de um vetor de números que você acredita vir de uma distribuição univariada contínua (por exemplo, uma distribuição normal) está definindo e usando a seguinte função:

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

Então, para obter a estimativa de modo:

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
Rasmus Bååth
fonte
3
Apenas uma observação sobre este: você pode obter um "modo" de qualquer grupo de números contínuos dessa maneira. Os dados não precisam vir de uma distribuição normal para funcionar. Aqui está um exemplo de números de uma distribuição uniforme. set.seed(1); a<-runif(100); mode<-density(a)$x[which.max(density(a)$y)]; abline(v=mode)
Jota
error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
Sérgio
@xhie Essa mensagem de erro informa tudo o que você precisa saber. Se você tiver apenas um ponto, precisará definir a largura de banda manualmente ao ligar density. No entanto, se você tiver apenas um datapoint então o valor do que datapoint será provavelmente o seu melhor palpite para o modo de qualquer maneira ...
Rasmus Baath
Você está certo, mas eu adicionei apenas um ajuste: estimate_mode <- function(x) { if (length(x)>1){ d <- density(x) d$x[which.max(d$y)] }else{ x } } estou testando o método para estimar a direção predominante do vento, em vez da média da direção, usando a média vetorial com pacote circular. Eu ', trabalhando com pontos acima de uma grade de polígono, então, às vezes, há apenas um ponto com direção. Obrigado!
Sérgio
@xhie Parece razoável :)
Rasmus Baath
14

A seguinte função vem em três formas:

method = "mode" [padrão]: calcula o modo para um vetor unimodal, mas retorna um
método NA = "nmodes": calcula o número de modos no vetor
method = "modes": lista todos os modos de um unimodal ou polmodal vetor

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()
}
Chris
fonte
Na descrição dessas funções, você trocou "modos" e "nmodes". Veja o código. Na verdade, "nmodes" retorna o vetor de valores e "modos" retorna o número de modos. Mesmo assim, sua função é a melhor alma gêmea para encontrar modos que já vi até agora.
Grzegorz Adam Kowalski
Muito obrigado pelo comentário. "nmode" e "modos" agora devem se comportar conforme o esperado.
21715 Chris
Sua função funciona quase, exceto quando cada valor ocorre com a mesma frequência de uso method = 'modes'. Em seguida, a função retorna todos os valores exclusivos, no entanto, na verdade, não há modo, portanto, ele deve retornar NA. Vou adicionar outra resposta contendo uma versão ligeiramente otimizada da sua função, obrigado pela inspiração!
hugovdberg
A única vez em que um vetor numérico não vazio normalmente deve gerar um NA com esta função é ao usar o método padrão em um vetor polimodal. O modo de uma sequência simples de números como 1,2,3,4 é na verdade todos esses números na sequência, portanto, para sequências semelhantes, os "modos" estão se comportando conforme o esperado. por exemplo, modeave (c (1,2,3,4), method = "modes") retorna [1] 1 2 3 4 Independentemente disso, eu ficaria muito interessado em ver a função otimizada, pois é bastante intensiva em termos de recursos. estado atual
Chris
Para uma versão mais eficiente desta função, ver @ do hugovdberg post acima :)
Chris
10

Aqui, outra solução:

freq <- tapply(mySamples,mySamples,length)
#or freq <- table(mySamples)
as.numeric(names(freq)[which.max(freq)])
teucer
fonte
Você pode substituir a primeira linha pela tabela.
Jonathan Chang
Eu estava pensando que 'tapply' é mais eficiente que 'table', mas ambos usam um loop for. Eu acho que a solução com tabela é equivalente. Eu atualizo a resposta.
Teucer
9

Ainda não posso votar, mas a resposta de Rasmus Bååth é o que eu estava procurando. No entanto, eu o modificaria um pouco, permitindo restringir a distribuição, por exemplo, para valores apenas entre 0 e 1.

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

Sabemos que você pode não querer restringir toda a sua distribuição e defina de = - "NÚMERO GRANDE" a = "NÚMERO GRANDE"

AleRuete
fonte
error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
Sérgio
x deve ser um vector
AleRuete
8

Uma pequena modificação na resposta de Ken Williams, adicionando parâmetros opcionais na.rme return_multiple.

Diferentemente das respostas names(), essa resposta mantém o tipo de dados xno (s) valor (es) retornado (s).

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

Para mostrar que funciona com os parâmetros opcionais e mantém o tipo de dados:

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"

Obrigado a @Frank pela simplificação.

C8H10N4O2
fonte
7

Eu escrevi o código a seguir para gerar o modo.

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

Vamos tentar:

MODE(mtcars)
MODE(CO2)
MODE(ToothGrowth)
MODE(InsectSprays)
Tyler Rinker
fonte
6

Com base na função de @ Chris para calcular o modo ou métricas relacionadas, porém usando o método de Ken Williams para calcular frequências. Este fornece uma correção para o caso de nenhum modo (todos os elementos são igualmente frequentes) e alguns methodnomes mais legíveis .

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

Como ele usa o método de Ken para calcular frequências, o desempenho também é otimizado. Usando o post de AkselA, comparei algumas das respostas anteriores para mostrar como minha função está próxima da de Ken no desempenho, com as condicionais para as várias opções de saída, causando apenas uma pequena sobrecarga: Comparação de funções de modo

hugovdberg
fonte
O código que você apresenta parece ser uma cópia mais ou menos direta da Modefunção encontrada no pracmapacote. Gostaria de explicar?
precisa saber é o seguinte
Mesmo? Aparentemente, não sou o único a pensar que essa é uma boa maneira de calcular o Modo, mas sinceramente não sabia disso (nunca conheci esse pacote antes). Limpei a função de Chris e a aprimorei, aproveitando a versão de Ken, e se ela se parece com o código de outra pessoa, é pura coincidência.
Hugovdberg 03/07/19
Eu olhei para ele agora, mas a qual versão do pracmapacote você se refere? A versão 1.9.3 tem uma implementação completamente diferente, tanto quanto posso ver.
Hugovdberg 03/07/19
2
Boa alteração na função. Após algumas leituras adicionais, sou levado a concluir que não há consenso sobre se as distribuições uniformes ou de monofrequência têm nós, algumas fontes dizendo que a lista de modos são as próprias distribuições, outras que o não existe nó. O único acordo é que a produção de uma lista de modos para essas distribuições não é muito informativa nem particularmente significativa. Se deseja que a função acima para produzir modos tais casos, em seguida, remover a linha: nmodes <- ifelse (nmodes == n, 0D, nmodes)
Chris
11
@greendiod desculpe, eu perdi o seu comentário. Ele está disponível nesta lista: gist.github.com/Hugovdberg/0f00444d46efd99ed27bbe227bdc4d37
hugovdberg
6

Esse hack deve funcionar bem. Fornece o valor e a contagem do modo:

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

O R possui tantos pacotes complementares que alguns deles podem fornecer o modo [estatístico] de uma lista / série / vetor numérico.

No entanto, a biblioteca padrão do próprio R não parece ter um método embutido! Uma maneira de contornar isso é usar alguma construção como a seguinte (e transformá-la em uma função se você costuma usar ...):

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

Para uma lista de amostras maior, deve-se considerar o uso de uma variável temporária para o valor máximo (tabSmpl) (não sei se R otimizaria isso automaticamente)

Referência: consulte "Que tal mediana e modo?" nesta lição do KickStarting R
Isso parece confirmar que (pelo menos na redação desta lição) não há uma função de modo no R (bem ... mode (), como você descobriu que é usada para afirmar o tipo de variáveis )

mjv
fonte
3

Isso funciona muito bem

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

Aqui está uma função para encontrar o modo:

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)
}
Ernest S Kirubakaran
fonte
3

Abaixo está o código que pode ser usado para encontrar o modo de uma variável vetorial em R.

a <- table([vector])

names(a[a==max(a)])
GauravS
fonte
3

Existem várias soluções fornecidas para este. Eu verifiquei o primeiro e depois escrevi o meu. Colocá-lo aqui, se ajudar alguém:

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

Vamos testá-lo com alguns exemplos. Estou pegando o irisconjunto de dados. Permite testar com dados numéricos

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

que você pode verificar está correto.

Agora, o único campo não numérico no conjunto de dados da íris (Espécies) não possui um modo. Vamos testar com nosso próprio exemplo

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

EDITAR

Conforme mencionado nos comentários, o usuário pode querer preservar o tipo de entrada. Nesse caso, a função mode pode ser modificada para:

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

A última linha da função simplesmente restringe o valor do modo final ao tipo da entrada original.

Abhiroop Sarkar
fonte
Isso retorna um fator, enquanto o usuário provavelmente deseja preservar o tipo da entrada. Talvez adicionar um passo meioy[,1] <- sort(unique(x))
Frank
2

Eu usaria a função density () para identificar um máximo suavizado de uma distribuição (possivelmente contínua):

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

onde x é a coleta de dados. Preste atenção ao parâmetro de ajuste da função de densidade que regula a suavização.

Yo B.
fonte
2

Enquanto eu gosto da função simples de Ken Williams, gostaria de recuperar os vários modos, se existirem. Com isso em mente, uso a seguinte função, que retorna uma lista dos modos, se múltiplos ou únicos.

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)) )]
} 
RandallShanePhD
fonte
Seria mais consistente para uso programático se ele sempre retornou uma lista - de comprimento 1 se houver apenas um modo
ASAC
Esse é um ponto válido @ antoine-sac. O que eu gosto nessa solução é o vetor retornado, que deixa as respostas facilmente endereçáveis. Basta endereçar a saída da função: r <- mode (c (2, 2, 3, 3)) com os modos disponíveis em r [1] e r [2]. Ainda assim, você faz um bom argumento !!
RandallShanePhD
Precisamente, é aqui que sua solução fica aquém. Se moderetornar uma lista com vários valores, então r [1] não é o primeiro valor; em vez disso, é uma lista do comprimento 1 que contém o primeiro valor e você deve executar r [[1]] para obter o primeiro modo como numérico e não como lista. Agora, quando existe um modo único, seu r não é uma lista, então r [1] funciona, e é por isso que eu pensei que era inconsistente. Mas como r [[1]] também funciona quando r é um vetor simples, na verdade há uma consistência que eu não tinha percebido, que você sempre pode usar [[para acessar elementos.
ASAC
2

Eu estava analisando todas essas opções e comecei a me perguntar sobre suas características e desempenhos relativos, então fiz alguns testes. Caso alguém mais tenha curiosidade sobre o mesmo, estou compartilhando meus resultados aqui.

Não querendo se preocupar com todas as funções postadas aqui, optei por focar em uma amostra com base em alguns critérios: a função deve funcionar com caracteres, fatores, vetores lógicos e numéricos, deve lidar com NAs e outros valores problemáticos de forma adequada, e a saída deve ser 'sensata', ou seja, nenhum número como caractere ou outra bobagem.

Também adicionei uma função própria, que é baseada na mesma rleidéia que a de chrispy, exceto adaptada para uso mais geral:

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

Acabei executando cinco funções, em dois conjuntos de dados de teste microbenchmark. Os nomes das funções se referem aos seus respectivos autores:

insira a descrição da imagem aqui

A função de Chris foi definida como method="modes"ena.rm=TRUE por padrão para torná-la mais comparável, mas, além disso, as funções foram usadas conforme apresentadas aqui por seus autores.

Apenas em questão de velocidade, a versão Kens vence com facilidade, mas também é a única que relatará apenas um modo, não importa quantos realmente existam. Como costuma ser o caso, há uma troca entre velocidade e versatilidade. Na method="mode"versão de Chris retornará um valor se houver um modo, senão NA. Eu acho que é um toque legal. Também acho interessante como algumas das funções são afetadas por um número maior de valores únicos, enquanto outras não são quase o mesmo. Não estudei o código em detalhes para descobrir por que, além de eliminar a lógica / numérica como causa.

AkselA
fonte
2

O modo não pode ser útil em todas as situações. Portanto, a função deve resolver esta situação. Tente a seguinte função.

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

Resultado,

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."
Jibin
fonte
Desculpe, mas não vejo como isso adiciona algo novo ao que já foi publicado. Além disso, sua saída parece inconsistente com a sua função acima.
Not2qubit 11/0918
2

Isso se baseia na resposta de jprockbelly, adicionando uma velocidade para vetores muito curtos. Isso é útil ao aplicar o modo a um data.frame ou tabela de dados com vários grupos pequenos:

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)))]
}
Dan Houghton
fonte
1

Outra opção simples que fornece todos os valores ordenados por frequência é usar rle:

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

Outra solução possível:

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

Uso:

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

Resultado:

   user  system elapsed 
   0.32    0.00    0.31 
Naimish Agarwal
fonte
1

Caso suas observações sejam classes de números reais e você espera que o modo seja 2,5 quando suas observações forem 2, 2, 3 e 3, você poderá estimar o modo com mode = l1 + i * (f1-f0) / (2f1 - f0 - f2)onde l1 .. limite inferior da classe mais frequente, f1 . .frequency de classe mais frequente, f0 ..frequency das classes antes de mais classe frequente, f2 ..frequency das classes após mais frequente e classe i ..Class intervalo como determinado por exemplo, em 1 , 2 , 3 :

#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

Caso você deseje o nível mais frequente e possua mais de um nível mais frequente, poderá obter todos eles, por exemplo, com:

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

Adicionando uma possível abordagem data.table

library(data.table)
#for single mode
dtmode <- function(x) x[which.max(data.table::rowid(x))]

#for multiple modes
dtmodes <- function(x) x[{r <- rowid(x); r==max(r)}]
chinsoon12
fonte
1

Aqui estão várias maneiras de fazer isso em tempo de execução Theta (N)

from collections import defaultdict

def mode1(L):
    counts = defaultdict(int)
    for v in L:
        counts[v] += 1
    return max(counts,key=lambda x:counts[x])
def mode2(L):
    vals = set(L)
    return max(vals,key=lambda x: L.count(x))
def mode3(L):
    return max(set(L), key=lambda x: L.count(x))
Paul Sartre
fonte
0

Pode tentar a seguinte função:

  1. transformar valores numéricos em fator
  2. use summary () para obter a tabela de frequências
  3. modo de retorno o índice cuja frequência é a maior
  4. transformar o fator de volta para numérico, mesmo que haja mais de 1 modo, essa função funciona bem!
mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}
Wei
fonte
0

Modo de cálculo é principalmente no caso de variável fator, então podemos usar

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

HouseVotes84 é um conjunto de dados disponível no pacote 'mlbench'.

isso fornecerá o valor máximo do rótulo. é mais fácil usar as funções embutidas sem a função de gravação.

Ashutosh Agrahari
fonte
0

Parece-me que, se uma coleção tem um modo, seus elementos podem ser mapeados individualmente com os números naturais. Portanto, o problema de localizar o modo se reduz a produzir esse mapeamento, localizar o modo dos valores mapeados e, em seguida, mapear de volta para alguns dos itens da coleção. (Lidando comNA ocorre na fase de mapeamento).

Eu tenho uma histogramfunção que opera com um diretor semelhante. (As funções e operadores especiais usados ​​no código aqui apresentado devem ser definidos no Shapiro e / ou no neatOveRse . As partes do Shapiro e do neatOveRse duplicadas neste documento são duplicadas com permissão; os trechos duplicados podem ser usados ​​sob os termos deste site. ) R pseudocódigo para histogramé

.histogram <- function (i)
        if (i %|% is.empty) integer() else
        vapply2(i %|% max %|% seqN, `==` %<=% i %O% sum)

histogram <- function(i) i %|% rmna %|% .histogram

(Os operadores binários especiais realizam tubulação , currying e composição ). Também tenho uma maxlocfunção que é semelhante a which.max, mas retorna todos os máximos absolutos de um vetor. R pseudocódigo para maxlocé

FUNloc <- function (FUN, x, na.rm=F)
        which(x == list(identity, rmna)[[na.rm %|% index.b]](x) %|% FUN)

maxloc <- FUNloc %<=% max

minloc <- FUNloc %<=% min # I'M THROWING IN minloc TO EXPLAIN WHY I MADE FUNloc

Então

imode <- histogram %O% maxloc

e

x %|% map %|% imode %|% unmap

calculará o modo de qualquer coleção, desde que definidas as funções -ping mape -ping apropriadas unmap.

Ana Nimbus
fonte