Pregunta

R, mean() y median() son funciones estándar que hacen lo que se espera. mode() le indica el modo de almacenamiento interna del objeto, no el valor que se produce la mayor cantidad en su argumento. Pero es que hay una función de biblioteca estándar que implementa el modo de estadística para un vector (o lista)?

¿Fue útil?

Solución

Uno más solución, que funciona tanto para datos de caracteres numéricos y / factor de:

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

En mi máquina poco de mala muerte, que pueden generar y encontrar el modo de un vector 10M-número entero en aproximadamente medio segundo.

Si el conjunto de datos podría tener múltiples modos, la solución anterior tiene el mismo enfoque que which.max, y devuelve el de primera que aparece valor del conjunto de modos. Para volver todos modos, utilice esta variante (de @digEmAll en los comentarios):

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

Otros consejos

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

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 obtener más información, véase esta página

encontrado esto en la lista de correo r, espero que sea útil. También es lo que estaba pensando de todos modos. Usted querrá tabla () los datos, clasificar y luego escoger el nombre de pila. Es hacker pero debería funcionar.

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

he encontrado Ken Williams post anterior a ser grande, añadí unas pocas líneas para dar cuenta de los valores de NA y lo hice una función para la facilidad.

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

A manera rápida y sucia de estimar el modo de un vector de números usted cree que viene de una distribución univariante continua (por ejemplo, una distribución normal) es la definición y el uso de la siguiente función:

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

A continuación, para obtener la estimación 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

La siguiente función se presenta en tres formas:

method = "modo" [predeterminado]: Calcula el modo para un vector unimodal, devoluciones bien un NA
method = "nmodes": calcula el número de modos en el vector
Método = "modos": listas de todos los modos para una 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()
}

A continuación, otra solución:

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

No puede votar todavía, pero la respuesta de Rasmus Bååth es lo que estaba buscando. Sin embargo, yo modificarlo un poco permitiendo a contrain la distribución para los valores de ejemplo de vaivén sólo 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)]
}

Nos cuenta que no se puede querer limitar en absoluto su distribución, a continuación, establezca a partir = - "número grande", a = "número grande"

Una pequeña modificación de respuesta Ken Williams', añadiendo na.rm params opcional y return_multiple.

A diferencia de las respuestas depender de names(), esta respuesta mantiene el tipo de datos de x en el valor devuelto (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 trabaja con los parametros 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 de simplificación.

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

try de Hagámosle:

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

Sobre la base de la función de Chris @ para calcular el modo o las métricas relacionadas, sin embargo, utilizando el método de Ken Williams a frecuencias de calcular. Éste proporciona una solución para el caso de no hay modos en absoluto (todos los elementos igualmente frecuentes), y algunos nombres method 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 se usa el método de Ken a frecuencias calcular el rendimiento también se ha optimizado utilizando el post de Aksela I Benchmarked algunas de las respuestas anteriores como para mostrar cómo mi función está cerca de Ken en el rendimiento, con los condicionales para las diversas opciones ouput causando solamente sobrecarga de menor importancia: Comparación de las funciones Modo

Este truco debería funcionar bien. le da el valor, así como el modo de recuento de:

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

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

Sin embargo, la biblioteca estándar de R en sí no parece que tienen tales incorporado un método! Una forma de evitar esto es utilizar algún constructo como la siguiente (y para convertir esta a una función de si se utiliza 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

En la lista de muestra más grande, uno debe considerar el uso de una variable temporal para el máximo (tabSmpl) valor (no sé que sería R optimizar automáticamente esto)

Referencia: ver "¿Qué hay de mediana y la moda?" en este Kickstarting R lección
Esto parece confirmar que (al menos en el momento de redactar esta lección) no es una función del modo en R (así ... Modo () como descubriste se utiliza para hacer valer el tipo de variables).

Esto funciona bastante bien

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

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

I utilizaría la función de densidad () para identificar un máximo suavizada de una distribución (posiblemente continuo):

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

donde x es la recogida de datos. prestar atención a la ajustar Paremeter de la función de densidad que regulan el alisado.

Mientras yo como simple función Ken Williams, me gustaría recuperar los múltiples modos si es que existen. Con esto en mente, yo uso la siguiente función que devuelve una lista de los modos si es múltiple o la única.

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

Yo estaba mirando a través de todas estas opciones y empecé a preguntar acerca de sus características relativas y actuaciones, así que hice algunas pruebas. En caso de que nadie más curioso acerca de la misma, que estoy compartiendo mis resultados aquí.

No queriendo que preocuparse por todas las funciones publicados aquí, he optado por centrarse en una muestra basada en unos criterios: la función debería funcionar en ambos caracteres, factor, vectores lógicos y numéricos, se debe tratar con AN y otra problemática valores apropiadamente, y la salida deben ser 'sensible', es decir, no hay valores numéricos como el carácter u otro de tales necedad.

También añadió una función de la mía, que se basa en la misma idea rle como de Chrispy, excepto adaptado para su 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é corriendo cinco funciones, en dos conjuntos de datos de prueba, a través de microbenchmark. Los nombres de función se refieren a sus respectivos autores:

introducir descripción de la imagen aquí

Función de Chris se establece en method="modes" y na.rm=TRUE por defecto para que sea más comparable, pero aparte de eso se utilizaron las funciones como se presenta aquí por sus autores.

En cuestión de velocidad sola versión Kens gana facilmente, pero también es el único de éstos que sólo reportará un modo, no importa cuántos son en realidad. Como suele ser el caso, hay un compromiso entre velocidad y versatilidad. En method="mode", la versión de Chris se devuelve un valor si y sólo si existe un modo, otro NA. Creo que es un buen toque. También creo que es interesante cómo algunas de las funciones se ven afectados por un aumento del número de valores únicos, mientras que otros no lo son casi la misma cantidad. No he estudiado el código en detalle para entender por qué esto es, además de eliminar / numérico lógico como la causa.

A continuación se muestra el código que se puede utilizar para encontrar el modo de una variable del vector en I.

a <- table([vector])

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

Existen múltiples soluciones previstas para éste. Comprobé el primero de ellos y después de que escribí mi propia. Publicar aquí si ayuda a nadie:

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

Permite la prueba con unos cuantos ejemplo. Estoy tomando el conjunto de datos iris. Vamos a prueba con datos numéricos

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

que se puede verificar es correcta.

Ahora el campo sólo no numérico en el conjunto de datos del iris (especies) no tiene un modo. Prueba Vamos con nuestro propio ejemplo

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

editar

Como se ha mencionado en los comentarios, usuario podría querer conservar el tipo de entrada. En cuyo caso la función de modo puede ser modificado 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 de modo final al tipo de la entrada original.

Modo no puede ser útil en todas las situaciones. Por lo que la función debe hacer frente a esta situación. Pruebe 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."

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

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

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 

Esto se basa en la respuesta de jprockbelly, añadiendo una velocidad de vectores muy cortos. Esto es útil cuando se aplica de modo en un data.frame o tabla de datos con una gran cantidad de pequeños grupos:

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

Me caso de que sus observaciones son clases Los números reales y se puede esperar que el modo a ser 2,5 cuando sus observaciones son 2, 2, 3 y 3 Posteriormente, se podría estimar el modo con mode = l1 + i * (f1-f0) / (2f1 - f0 - f2) donde L1 .. límite inferior de la mayoría clase frecuente, F1 .. frecuencia de la clase más frecuente, f0 .. frecuencia de las clases antes que la mayoría de clase frecuentes, frecuencia f2 de las clases .. después de más frecuente y la clase 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 quiera la más frecuente nivel y tener más de un nivel más frecuente que puede llegar a todos ellos por ejemplo, con:

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

podría intentar la siguiente función:

  1. transformar los valores numéricos en el factor
  2. Resumen uso () para obtener la tabla de frecuencias
  3. Modo de retorno del índice cuya frecuencia es la más grande
  4. transformará de nuevo factor a numérico, incluso 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)
}

Modo de cálculo es sobre todo en el caso de la variable de factor entonces podemos usar

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

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

dará valor de etiqueta max. es más fácil de usar por sí mismo las funciones incorporadas sin la función de la escritura.

Lo siento, lo podría tomar demasiado simple, pero no esta hacer el trabajo? (En 1,3 segundos para 1E6 valores en mi máquina):

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

Sólo tiene que sustituir el "redondo (rnorm (1E6), 2)" con su vector.

También podría calcular el número de veces que una instancia que ha ocurrido en su conjunto y encontrar el número máx. por ejemplo.

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

Una manera fácil de MODO calcular de un vector 'v' que contiene valores discretos es:

names(sort(table(v)))[length(sort(table(v)))]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top