superponer - titles in r plots
¿Hay una función incorporada para encontrar el modo? (29)
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)])
En R, mean()
y median()
son funciones estándar que hacen lo que cabría esperar. mode()
le indica el modo de almacenamiento interno del objeto, no el valor que más ocurre en su argumento. ¿Pero hay una función de biblioteca estándar que implementa el modo estadístico para un vector (o lista)?
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)
}
Aquí, otra solución:
freq <- tapply(mySamples,mySamples,length)
#or freq <- table(mySamples)
as.numeric(names(freq)[which.max(freq)])
Basado en la función de @ Chris para calcular el modo o las métricas relacionadas, sin embargo, se usa el método de Ken Williams para calcular las frecuencias. Este proporciona una solución para el caso de que no haya modos (todos los elementos igualmente frecuentes), y algunos nombres de 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 utiliza el método de Ken para calcular las frecuencias, el rendimiento también se optimiza, al usar la publicación de AkselA, comparé algunas de las respuestas anteriores para mostrar cómo mi función está cerca de la de Ken en el rendimiento, con los condicionales para las diversas opciones de salida que causan solo una pequeña sobrecarga:
El modo de cálculo es mayormente en el caso de la variable 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 las funciones incorporadas sin la función de escritura.
El modo no puede ser útil en todas las situaciones. Así que la función debe 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."
Encontré esto en la lista de correo de r, espero que sea útil. También es lo que estaba pensando de todos modos. Querrá hacer una tabla () de los datos, ordenar y luego elegir el primer nombre. Es pirata pero debería funcionar.
names(sort(-table(x)))[1]
Encontré que la publicación de Ken Williams anterior es excelente, agregué algunas líneas para explicar los valores de NA y la hice una función para facilitar la tarea.
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)))])
}
Estaba revisando todas estas opciones y comencé a preguntarme sobre 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í.
Sin querer preocuparme por todas las funciones publicadas aquí, elegí enfocarme en una muestra basada en unos pocos criterios: la función debería funcionar en ambos caracteres, factores, vectores lógicos y numéricos, debería tratar las NA y otros valores problemáticos de manera apropiada. y la salida debe ser ''sensible'', es decir, no numéricos como carácter u otra tontería.
También agregué una función propia, que se basa en la misma idea 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 de microbenchmark
. Los nombres de funciones se refieren a sus respectivos autores:
La función de Chris se estableció en method="modes"
y na.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 cuanto a la velocidad, la versión de Kens gana fácilmente, pero también es la única de estas que solo reportará un modo, sin importar cuántos haya en realidad. Como suele ser el caso, existe un equilibrio entre la velocidad y la 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 de las 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 averiguar por qué, además de eliminar la causa lógica / numérica.
Este truco debería funcionar bien. Le da el valor, así como el recuento de modo:
Mode <- function(x){
a = table(x) # x is a vector
return(a[which.max(a)])
}
Esto funciona bastante bien
> a<-c(1,1,2,2,3,3,4,4,5)
> names(table(a))[table(a)==max(table(a))]
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:
t0 <- Sys.time()
summary(as.factor(round(rnorm(1e6), 2)))[1]
Sys.time()-t0
Hay múltiples soluciones para este caso. Revisé el primero y después escribí el mío. Publicándolo 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 conjunto de datos del iris
. Permite la prueba con datos numéricos.
> Mode(iris$Sepal.Length)
[1] 5
Lo que puedes verificar es correcto.
Ahora, el único campo no numérico en el conjunto de datos del iris (Especie) no tiene un modo. Probemos con nuestro propio ejemplo.
> test <- c("red","red","green","blue","red")
> Mode(test)
[1] red
EDITAR
Como se mencionó en los comentarios, el usuario puede querer preservar 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 obliga al valor del modo final al tipo de la entrada original.
Hay un modo de paquete que proporciona estimadores del modo de datos unimodales unimodales (y en ocasiones multimodales) y valores de los modos de las 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 vea esta página.
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)
La siguiente función viene en tres formas:
method = "mode" [predeterminado]: calcula el modo para un vector unimodal; de lo contrario, devuelve un NA
method = "nmodes": calcula el número de modos en el vector
method = "modes": enumera todos los modos para un vector unimodal o polimodal
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()
}
Lo siento, podría ser demasiado simple, pero ¿esto no funciona? (en 1.3 segundos para los valores de 1E6 en mi máquina):
> 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
>
Solo tiene que reemplazar la "ronda (rnorm (1e6), 2)" con su vector.
No puedo votar todavía, pero la respuesta de Rasmus Bååth es lo que estaba buscando. Sin embargo, lo modificaría un poco, lo que permitiría restringir la distribución, por ejemplo, para valores de 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 toda su distribución, luego establezca desde = - "NÚMERO GRANDE", a = "NÚMERO GRANDE"
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)
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
Podría probar la siguiente función:
- transformar valores numéricos en factor
- usar sumario () para obtener la tabla de frecuencias
- modo de retorno el índice cuya frecuencia es la más grande
- transforme el factor de nuevo a 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)
}
R tiene tantos paquetes complementarios que algunos de ellos pueden proporcionar el modo [estadístico] de una lista / serie / vector numérico.
Sin embargo, ¡la biblioteca estándar de R en sí misma no parece tener un método incorporado! Una forma de evitar esto es usar una construcción como la siguiente (y convertirla 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 obtener una lista de muestra más grande, se debe considerar el uso de una variable temporal para el valor máximo (tabSmpl) (no sé si R optimizaría esto automáticamente)
Referencia: ver "¿Qué hay de la mediana y el modo?" 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 () que descubrió se usa para confirmar el tipo de variables).
Si bien me gusta la función simple de Ken Williams, me gustaría recuperar los modos múltiples si existen. Teniendo eso en cuenta, utilizo 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)) )]
}
También puede calcular el número de veces que ha ocurrido una instancia en su conjunto y encontrar el número máximo. p.ej
names(sort(table(v)))[length(sort(table(v)))]
Una forma fácil de calcular el MODO de un vector ''v'' que contiene valores discretos es:
names(sort(table(v)))[length(sort(table(v)))]
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 la estimación 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
Una pequeña modificación a la respuesta de Ken Williams, agregando params opcionales na.rm
y return_multiple
.
A diferencia de las respuestas que se basan en los names()
, esta respuesta mantiene el tipo de datos de x
en los 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 mostrarlo 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.
Una solución más, que funciona para datos tanto numéricos como de caracteres / factores:
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
En mi pequeña máquina, que 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 que which.max
y devuelve el primer valor aparente 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)]
}
Yo usaría la función de 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.