¿Hay una función incorporada para encontrar el modo?

392

En R, mean()y median()son funciones estándar que hacen lo que cabría esperar. mode()le dice el modo de almacenamiento interno del objeto, no el valor que ocurre más en su argumento. Pero, ¿existe una función de biblioteca estándar que implemente el modo estadístico para un vector (o lista)?

Mella
fuente
44
¿Necesita aclarar si sus datos son enteros, numéricos, factor ...? La estimación del modo numérico será diferente y usa intervalos. Ver modeest
SMCI
2
¿Por qué R no tiene una función incorporada para el modo? ¿Por qué considera R modelo mismo que la función class?
Corey Levinson el

Respuestas:

400

Una solución más, que funciona para datos numéricos y de caracteres / factores:

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

En mi pequeña máquina pequeña, eso puede generar y encontrar el modo de un vector entero de 10M en aproximadamente medio segundo.

Si su conjunto de datos puede tener múltiples modos, la solución anterior toma el mismo enfoque which.maxy devuelve el valor que aparece por primera vez del conjunto de modos. Para devolver todos los modos, use esta variante (de @digEmAll en los comentarios):

Modes <- function(x) {
  ux <- unique(x)
  tab <- tabulate(match(x, ux))
  ux[tab == max(tab)]
}
Ken Williams
fuente
77
¡También funciona para lógicos! Conserva el tipo de datos para todos los tipos de vectores (a diferencia de algunas implementaciones en otras respuestas).
DavidC
39
Esto no devuelve todos los modos en caso de conjunto de datos multimodal (por ejemplo c(1,1,2,2)). Debería cambiar su última línea con:tab <- tabulate(match(x, ux)); ux[tab == max(tab)]
digEmAll
66
@verybadatthis Para eso, lo reemplazaría ux[which.max(tabulate(match(x, ux)))]con solo max(tabulate(match(x, ux))).
Ken Williams
44
Nota que Mode(1:3)da 1y Mode(3:1)da 3, por lo que el modo devuelve el elemento más frecuente o el primero si todos son únicos.
Enrique Pérez Herrero
2
Como dijo Enrique: esto falla cuando no hay modo, y en cambio le da la impresión de que el primer valor es el modo. Hubiera sido mucho mejor si regresara 0o NAen esos casos.
not2qubit
66

Hay paquete modeest que proporciona estimadores del modo de datos univariados unimodales (y a veces multimodales) y valores de los modos de distribuciones de probabilidad habituales.

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 más información ver esta página

George Dontas
fuente
77
Así que acaba de obtener el valor de modo, mfv(mySamples)[1]. El 1ser importante ya que en realidad devuelve el valor más frecuente s .
atomicules
no parece funcionar en este ejemplo: biblioteca (modesta) a <- tormenta (50, 30, 2) b <- tormenta (100, 35, 2) c <- tormenta (20, 37, 2) temperaturaºC <- c (a, b, c) hist (temperatura ºC) # abline media (v = media (temperatura ºC), col = "rojo", lwd = 2) # abline media (v = mediana (temperatura ºC), col = "negro", lwd = 2) #mode abline (v = mlv (temperaturaºC, método = "mfv") [1], col = "naranja", lwd = 2)
Agus camacho
1
@atomicules: con [1] obtienes solo el primer modo. Para la distribución bimodal o general n-modal, solo necesitaríamfv(mySamples)
petzi
1
Para R versión 3.6.0, dice que la función 'no pudo encontrar la función "mlv"' y el mismo error cuando probé mfv (mysamples). ¿Se deprecia?
Dra. Nisha Arora
@DrNishaArora: ¿Descargó el paquete 'más modesto'?
Petzi
59

Encontré esto en la lista de correo, espero que sea útil. También es lo que estaba pensando de todos modos. Querrás poner en la tabla () los datos, ordenarlos y luego elegir el nombre. Es hack pero debería funcionar.

names(sort(-table(x)))[1]
Dan
fuente
66
Esa también es una solución inteligente. Tiene algunos inconvenientes: el algoritmo de ordenamiento puede consumir más espacio y tiempo que los enfoques basados ​​en max () (=> a evitar para listas de muestra más grandes). También la salida es de modo (perdón por el juego de palabras / ambigüedad) "carácter" no "numérico". Y, por supuesto, la necesidad de probar la distribución multimodal generalmente requeriría el almacenamiento de la tabla ordenada para evitar volver a comprimirla.
mjv
2
¡Medí el tiempo de ejecución con un factor de 1e6 elementos y esta solución fue más rápida que la respuesta aceptada por casi el factor 3!
vonjd
Acabo de convertirlo en número usando as.numeric (). Funciona perfectamente bien. ¡Gracias!
Abhishek Singh
47

Encontré que la publicación de Ken Williams anterior es excelente, agregué algunas líneas para tener en cuenta los valores de NA y la convertí en una función fácil.

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
fuente
He encontrado un par de aceleraciones para esto, vea la respuesta a continuación.
Dan Houghton el
33

Una forma rápida y sucia de estimar el modo de un vector de números que cree que provienen de una distribución univariada continua (por ejemplo, una distribución normal) es definir y utilizar la siguiente función:

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

Luego para obtener el modo estimado:

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
fuente
3
Solo una nota sobre esto: puede obtener un "modo" de cualquier grupo de números continuos de esta manera. Los datos no necesitan provenir de una distribución normal para funcionar. Aquí hay un ejemplo que toma números de una distribución 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
Sergio
@xhie Ese mensaje de error te dice todo lo que necesitas saber. Si solo tiene un punto, debe establecer el ancho de banda manualmente al llamar density. Sin embargo, si solo tiene un punto de datos, el valor de ese punto de datos probablemente será su mejor suposición para el modo de todos modos ...
Rasmus Bååth
Tienes razón, pero agregué solo un ajuste: estimate_mode <- function(x) { if (length(x)>1){ d <- density(x) d$x[which.max(d$y)] }else{ x } } estoy probando el método para estimar la dirección predominante del viento, en lugar de la media de la dirección usando el promedio vectorial con paquete circular. I ', trabajando con puntos sobre un grado de polígono, entonces, a veces solo hay un punto con dirección. ¡Gracias!
Sergio
@xhie Suena razonable :)
Rasmus Bååth
14

La siguiente función viene en tres formas:

method = "mode" [default]: calcula el modo para un vector unimodal, de lo contrario devuelve un
método NA = "nmodes": calcula el número de modos en el vector
method = "modes": enumera todos los modos para unimodal o polimodal vector

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
fuente
En su descripción de estas funciones, intercambió "modos" y "nmodes". Mira el código. En realidad, "nmodes" devuelve el vector de valores y "modos" devuelve el número de modos. Sin embargo, su función es la mejor opción para encontrar modos que he visto hasta ahora.
Grzegorz Adam Kowalski
Muchas gracias por el comentario. "nmode" y "modes" ahora deberían comportarse como se esperaba.
Chris
Su función funciona casi, excepto cuando cada valor ocurre con la misma frecuencia method = 'modes'. Luego, la función devuelve todos los valores únicos, sin embargo, en realidad no hay modo, por lo que debería volver NAen su lugar. Agregaré otra respuesta que contenga una versión ligeramente optimizada de su función, ¡gracias por la inspiración!
hugovdberg
El único momento en que un vector numérico no vacío normalmente debería generar un NA con esta función es cuando se utiliza el método predeterminado en un vector polimodal. El modo de una secuencia simple de números como 1,2,3,4 es en realidad todos esos números en la secuencia, por lo que para secuencias similares los "modos" se comportan como se esperaba. por ejemplo, modeave (c (1,2,3,4), method = "modes") devuelve [1] 1 2 3 4 Independientemente de esto, estaría muy interesado en ver la función optimizada ya que consume bastante recursos en su estado actual
Chris
Para una versión más eficiente de esta función, vea la publicación de @ hugovdberg arriba :)
Chris
10

Aquí, otra solución:

freq <- tapply(mySamples,mySamples,length)
#or freq <- table(mySamples)
as.numeric(names(freq)[which.max(freq)])
teucer
fuente
Puede reemplazar la primera línea con la tabla.
Jonathan Chang
Estaba pensando que 'tapply' es más eficiente que 'table', pero ambos usan un bucle for. Creo que la solución con tabla es equivalente. Actualizo la respuesta.
teucer
9

Todavía no puedo votar, pero la respuesta de Rasmus Bååth es lo que estaba buscando. Sin embargo, lo modificaría un poco, lo que permitiría contrainformar la distribución, por ejemplo, para valores solo entre 0 y 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 es posible que no desee restringir en absoluto su distribución, luego establezca desde = - "BIG NUMBER" a = "BIG NUMBER"

AleRuete
fuente
error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
Sergio
x debería ser un vector
AleRuete
8

Una pequeña modificación a la respuesta de Ken Williams, agregando parámetros opcionales na.rmyreturn_multiple .

A diferencia de las respuestas en las que se basa names(), esta respuesta mantiene el tipo de datos de xlos valores devueltos.

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 con los parámetros opcionales y mantiene el tipo de datos:

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"

Gracias a @Frank por la simplificación.

C8H10N4O2
fuente
7

He escrito el siguiente código para generar el 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 a intentarlo:

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

Basado en la función de @ Chris para calcular el modo o las métricas relacionadas, sin embargo, utilizando el método de Ken Williams para calcular las frecuencias. Este proporciona una solución para el caso de ningún modo en absoluto (todos los elementos igualmente frecuentes) y algunos methodnombres más legibles .

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

Dado que utiliza el método de Ken para calcular las frecuencias, el rendimiento también está optimizado, utilizando la publicación de AkselA comparé algunas de las respuestas anteriores para mostrar cómo mi función está cerca del rendimiento de Ken, con los condicionales para las diversas opciones de salida que causan solo una sobrecarga menor: Comparación de funciones de modo

hugovdberg
fuente
El código que presenta parece ser una copia más o menos directa de la Modefunción que se encuentra en el pracmapaquete. ¿Le importaria explicar?
AkselA
De Verdad? Aparentemente, no soy el único que piensa que esta es una buena manera de calcular el Modo, pero honestamente no lo sabía (nunca antes conocí ese paquete). Limpié la función de Chris y la mejoré aprovechando la versión de Ken, y si se parece al código de otra persona, es pura coincidencia.
hugovdberg
Lo investigué hace un momento, pero ¿a qué versión del pracmapaquete se refiere? La versión 1.9.3 tiene una implementación completamente diferente por lo que puedo ver.
hugovdberg
2
Buena enmienda a la función. Después de leer un poco más, llegué a la conclusión de que no hay consenso sobre si las distribuciones uniformes o monofrecuencia tienen nodos, algunas fuentes dicen que la lista de modos son las distribuciones mismas, otras que no hay ningún nodo. El único acuerdo es que producir una lista de modos para tales distribuciones no es muy informativo ni particularmente significativo. SI desea que la función anterior produzca modos en estos casos, elimine la línea: nmodes <- ifelse (nmodes == n, 0L, nmodes)
Chris
1
@greendiod lo siento, me perdí tu comentario. Está disponible a través de este resumen
hugovdberg
6

Este truco debería funcionar bien. Te da el valor y el conteo del modo:

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

R tiene tantos paquetes adicionales que algunos de ellos pueden proporcionar el modo [estadístico] de una lista numérica / serie / vector.

¡Sin embargo, la biblioteca estándar de R en sí no parece tener un método tan integrado! Una forma de evitar esto es usar alguna construcción como la siguiente (y convertir esto en una función si la usa a menudo ...):

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 una lista de muestra más grande, uno debería considerar usar una variable temporal para el valor máximo (tabSmpl) (no sé si R optimizaría esto automáticamente)

Referencia: consulte "¿Qué tal la mediana y la moda?" en esta lección de KickStarting R
Esto parece confirmar que (al menos al momento de escribir esta lección) no hay una función de modo en R (bueno ... el modo () como descubriste se usa para afirmar el tipo de variables )

mjv
fuente
3

Esto funciona bastante bien

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

Aquí hay una función para encontrar el 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
fuente
3

A continuación se muestra el código que se puede usar para encontrar el modo de una variable vectorial en R.

a <- table([vector])

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

Hay múltiples soluciones proporcionadas para este. Revisé el primero y luego escribí el mío. Publicarlo aquí si ayuda a alguien:

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

Vamos a probarlo con algunos ejemplos. Estoy tomando el irisconjunto de datos. Vamos a probar con datos numéricos

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

que puedes verificar es correcto.

Ahora el único campo no numérico en el conjunto de datos del iris (Especie) no tiene modo. Probemos con nuestro propio ejemplo

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

EDITAR

Como se menciona en los comentarios, el usuario puede querer conservar el tipo de entrada. En cuyo caso, la función de modo se puede modificar para:

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

La última línea de la función simplemente coacciona el valor del modo final al tipo de la entrada original.

Abhiroop Sarkar
fuente
Esto devuelve un factor, mientras que el usuario probablemente quiera preservar el tipo de entrada. Tal vez agregue un paso intermedioy[,1] <- sort(unique(x))
Frank
2

Usaría la función densidad () para identificar un máximo suavizado de una distribución (posiblemente continua):

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

donde x es la recopilación de datos. Preste atención al parámetro de ajuste de la función de densidad que regula el suavizado.

Yo B.
fuente
2

Si bien me gusta la función simple de Ken Williams, me gustaría recuperar los modos múltiples si existen. Con eso en mente, uso la siguiente función que devuelve una lista de los modos si es múltiple o único.

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
fuente
Sería más consistente para el uso programático si siempre devuelve una lista, de longitud 1 si solo hay un modo
como el
Ese es un punto válido @ antoine-sac. Lo que me gusta de esta solución es que el vector que se devuelve deja las respuestas fácilmente direccionables. Simplemente aborde la salida de la función: r <- modo (c (2, 2, 3, 3)) con los modos disponibles en r [1] yr [2]. ¡Aún así, haces un buen punto!
RandallShanePhD
Precisamente, aquí es donde su solución se queda corta. Si modedevuelve una lista con varios valores, entonces r [1] no es el primer valor; en cambio, es una lista de longitud 1 que contiene el primer valor y debe hacer r [[1]] para obtener el primer modo como un número y no como una lista. Ahora, cuando hay un modo único, su r no es una lista, por lo que r [1] funciona, por eso pensé que era inconsistente. Pero dado que r [[1]] también funciona cuando r es un vector simple, en realidad hay una consistencia que no me había dado cuenta de que siempre se puede usar [[para acceder a los elementos.
asac
2

Estaba examinando todas estas opciones y comencé a preguntarme acerca de sus características y actuaciones relativas, así que hice algunas pruebas. En caso de que alguien más tenga curiosidad por lo mismo, estoy compartiendo mis resultados aquí.

Como no quería preocuparme por todas las funciones publicadas aquí, decidí centrarme en una muestra basada en algunos criterios: la función debería funcionar tanto en vectores de caracteres, factores, lógicos y numéricos, debería tratar los NA y otros valores problemáticos de manera adecuada, y la salida debe ser "sensata", es decir, sin números como caracteres u otras tonterías.

También agregué una función propia, que se basa en la misma rleidea que la de chrispy, excepto que está adaptada para un uso más general:

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

Terminé ejecutando cinco funciones, en dos conjuntos de datos de prueba, a través microbenchmark. Los nombres de las funciones se refieren a sus respectivos autores:

ingrese la descripción de la imagen aquí

La función de Chris se estableció en method="modes"yna.rm=TRUE de forma predeterminada para que sea más comparable, pero aparte de eso, las funciones se usaron tal como las presentaron sus autores.

Solo en cuestión de velocidad, la versión de Kens gana fácilmente, pero también es el único de estos que solo informará un modo, sin importar cuántos haya realmente. Como suele ser el caso, hay una compensación entre velocidad y versatilidad. En method="mode", la versión de Chris devolverá un valor si hay un modo, de lo contrario NA. Creo que es un buen toque. También creo que es interesante cómo algunas funciones se ven afectadas por un mayor número de valores únicos, mientras que otras no lo son tanto. No he estudiado el código en detalle para entender por qué, aparte de eliminar la lógica / numérica como la causa.

AkselA
fuente
2

El modo no puede ser útil en todas las situaciones. Entonces la función debería abordar esta situación. Prueba la siguiente función.

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

Salida,

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
fuente
Lo siento, simplemente no veo cómo esto agrega algo nuevo a lo que ya se ha publicado. Además, su salida parece inconsistente con su función anterior.
not2qubit
2

Esto se basa en la respuesta de jprockbelly, al agregar una velocidad para vectores muy cortos. Esto es útil cuando se aplica el modo a un data.frame o datatable con muchos grupos pequeños:

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

Otra opción simple que da todos los valores ordenados por frecuencia es usar rle:

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

Otra posible solución:

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

Salida:

   user  system elapsed 
   0.32    0.00    0.31 
Naimish Agarwal
fuente
1

Me caso de que sus observaciones son las clases de números reales y se puede esperar que el modo de ser de 2,5 cuando sus observaciones son 2, 2, 3 y 3 Posteriormente, se podría estimar el modo en mode = l1 + i * (f1-f0) / (2f1 - f0 - f2)donde L1 ..lower límite de la mayoría de clase frecuentes, f1 . .frecuencia de la clase más frecuente, f0 ..frecuencia de clases antes de la clase más frecuente, f2 ..frecuencia de clases después de la clase más frecuente e i .. Intervalo de clase como se da, por ejemplo, en 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

En caso de que desee el nivel más frecuente y tenga más de un nivel más frecuente, puede obtenerlos todos, por ejemplo, con:

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

Agregar un posible enfoque de 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
fuente
1

Aquí hay varias formas de hacerlo en tiempo de ejecución 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
fuente
0

Podría probar la siguiente función:

  1. transformar valores numéricos en factor
  2. use summary () para obtener la tabla de frecuencias
  3. modo de retorno el índice cuya frecuencia es la más grande
  4. El factor de transformación vuelve a ser numérico, incluso si hay más de 1 modo, ¡esta función funciona bien!
mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}
Wei
fuente
0

El modo de cálculo es principalmente en el caso de la variable de factor, entonces podemos usar

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

HouseVotes84 es un conjunto de datos disponible en el paquete 'mlbench'.

le dará el valor máximo de la etiqueta. es más fácil de usar por funciones incorporadas sin escribir la función.

Ashutosh Agrahari
fuente
0

Me parece que si una colección tiene un modo, sus elementos pueden asignarse uno a uno con los números naturales. Por lo tanto, el problema de encontrar el modo se reduce a producir dicho mapeo, encontrar el modo de los valores mapeados y luego volver a mapear algunos de los elementos de la colección. (El tratamiento se NAproduce en la fase de mapeo).

Tengo una histogramfunción que opera en un director similar. (Las funciones y operadores especiales utilizados en el código presentado en este documento deben definirse en Shapiro y / o neatOveRse . Las partes de Shapiro y neatOveRse duplicadas en este documento se duplican con permiso; los fragmentos duplicados se pueden usar bajo los términos de este sitio. ) R pseudocódigo para histogramis

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

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

(Los operadores binarios especiales logran tuberías , curry y composición ) También tengo una maxlocfunción, que es similar a which.max, pero devuelve todos los máximos absolutos de un vector. R pseudocódigo para maxlocis

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

Entonces

imode <- histogram %O% maxloc

y

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

calculará el modo de cualquier colección, siempre que se mapdefinan las funciones apropiadas de -ping y unmap-ping.

Ana Nimbus
fuente