В R, mean()
и median()
- стандартные функции, которые делают то, что вы ожидаете. mode()
указывает режим внутреннего хранения объекта, а не значение, которое больше всего встречается в его аргументе. Но существует ли стандартная библиотечная функция, которая реализует статистический режим для вектора (или списка)?
Еще одно решение, которое работает как для числовых, так и для символьных/факторных данных:
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
На моей маленькой маленькой машине, которая может генерировать и находить режим вектора 10 М-целого примерно через полсекунды.
c(1,1,2,2)
). Вы должны изменить свою последнюю строку следующим образом: tab <- tabulate(match(x, ux)); ux[tab == max(tab)]
Существует пакет modeest
, который предоставляет оценки режима одномерных унимодальных (а иногда и мультимодальных) данных и значений режимов обычных распределений вероятностей.
mySamples <- c(19, 4, 5, 7, 29, 19, 29, 13, 25, 19)
library(modeest)
mlv(mySamples, method = "mfv")
Mode (most likely value): 19
Bickel modal skewness: -0.1
Call: mlv.default(x = mySamples, method = "mfv")
Для получения дополнительной информации см. эту страницу
mfv(mySamples)[1]
. Значение 1
важно, так как оно возвращает наиболее частое значение s .
нашел это в списке рассылки r, надеюсь, что это будет полезно. Это то, о чем я и думал. Вам нужно будет таблицы() данных, сортировки, а затем выбрать первое имя. Он взламывает, но должен работать.
names(sort(-table(x)))[1]
Я нашел пост Кен Уильямса выше, я добавил несколько строк для учета значений NA и сделал его функцией для удобства.
Mode <- function(x, na.rm = FALSE) {
if(na.rm){
x = x[!is.na(x)]
}
ux <- unique(x)
return(ux[which.max(tabulate(match(x, ux)))])
}
Быстрый и грязный способ оценки режима вектора чисел, который, по вашему мнению, поступает из непрерывного одномерного распределения (например, нормального распределения), определяет и использует следующую функцию:
estimate_mode <- function(x) {
d <- density(x)
d$x[which.max(d$y)]
}
Затем, чтобы получить оценку режима:
x <- c(5.8, 5.6, 6.2, 4.1, 4.9, 2.4, 3.9, 1.8, 5.7, 3.2)
estimate_mode(x)
## 5.439788
set.seed(1); a<-runif(100); mode<-density(a)$x[which.max(density(a)$y)]; abline(v=mode)
error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
Следующая функция имеет три формы:
method = "mode" [default]: вычисляет режим для унимодального вектора, else возвращает NA method = "nmodes": вычисляет количество режимов в векторе method = "modes": перечисляет все режимы для унимодального или полимодального вектора
modeav <- function (x, method = "mode", na.rm = FALSE)
{
x <- unlist(x)
if (na.rm)
x <- x[!is.na(x)]
u <- unique(x)
n <- length(u)
#get frequencies of each of the unique values in the vector
frequencies <- rep(0, n)
for (i in seq_len(n)) {
if (is.na(u[i])) {
frequencies[i] <- sum(is.na(x))
}
else {
frequencies[i] <- sum(x == u[i], na.rm = TRUE)
}
}
#mode if a unimodal vector, else NA
if (method == "mode" | is.na(method) | method == "")
{return(ifelse(length(frequencies[frequencies==max(frequencies)])>1,NA,u[which.max(frequencies)]))}
#number of modes
if(method == "nmode" | method == "nmodes")
{return(length(frequencies[frequencies==max(frequencies)]))}
#list of all modes
if (method == "modes" | method == "modevalues")
{return(u[which(frequencies==max(frequencies), arr.ind = FALSE, useNames = FALSE)])}
#error trap the method
warning("Warning: method not recognised. Valid methods are 'mode' [default], 'nmodes' and 'modes'")
return()
}
Здесь другое решение:
freq <- tapply(mySamples,mySamples,length)
#or freq <- table(mySamples)
as.numeric(names(freq)[which.max(freq)])
Я не могу голосовать, но ответ Rasmus Bååth - это то, что я искал. Тем не менее, я бы немного изменил его, чтобы ограничить распространение, например, значениями от 0 до 1.
estimate_mode <- function(x,from=min(x), to=max(x)) {
d <- density(x, from=from, to=to)
d$x[which.max(d$y)]
}
Мы знаем, что вы можете не захотеть ограничить вообще свой дистрибутив, а затем установить из = - "БОЛЬШОЙ НОМЕР", чтобы = "БОЛЬШОЙ НОМЕР"
error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
Я написал следующий код для создания режима.
MODE <- function(dataframe){
DF <- as.data.frame(dataframe)
MODE2 <- function(x){
if (is.numeric(x) == FALSE){
df <- as.data.frame(table(x))
df <- df[order(df$Freq), ]
m <- max(df$Freq)
MODE1 <- as.vector(as.character(subset(df, Freq == m)[, 1]))
if (sum(df$Freq)/length(df$Freq)==1){
warning("No Mode: Frequency of all values is 1", call. = FALSE)
}else{
return(MODE1)
}
}else{
df <- as.data.frame(table(x))
df <- df[order(df$Freq), ]
m <- max(df$Freq)
MODE1 <- as.vector(as.numeric(as.character(subset(df, Freq == m)[, 1])))
if (sum(df$Freq)/length(df$Freq)==1){
warning("No Mode: Frequency of all values is 1", call. = FALSE)
}else{
return(MODE1)
}
}
}
return(as.vector(lapply(DF, MODE2)))
}
Попробуйте:
MODE(mtcars)
MODE(CO2)
MODE(ToothGrowth)
MODE(InsectSprays)
Этот хак должен работать нормально. Дает вам значение, а также счетчик режима:
Mode <- function(x){
a = table(x) # x is a vector
return(a[which.max(a)])
}
На основе функции @Chris для вычисления режима или связанных показателей, однако используя метод Кен Уильямса для расчета частот. Это обеспечивает исправление для случая без режимов (все элементы одинаково часты) и некоторые более читаемые имена method
.
Mode <- function(x, method = "one", na.rm = FALSE) {
x <- unlist(x)
if (na.rm) {
x <- x[!is.na(x)]
}
# Get unique values
ux <- unique(x)
n <- length(ux)
# Get frequencies of all unique values
frequencies <- tabulate(match(x, ux))
modes <- frequencies == max(frequencies)
# Determine number of modes
nmodes <- sum(modes)
nmodes <- ifelse(nmodes==n, 0L, nmodes)
if (method %in% c("one", "mode", "") | is.na(method)) {
# Return NA if not exactly one mode, else return the mode
if (nmodes != 1) {
return(NA)
} else {
return(ux[which(modes)])
}
} else if (method %in% c("n", "nmodes")) {
# Return the number of modes
return(nmodes)
} else if (method %in% c("all", "modes")) {
# Return NA if no modes exist, else return all modes
if (nmodes > 0) {
return(ux[which(modes)])
} else {
return(NA)
}
}
warning("Warning: method not recognised. Valid methods are 'one'/'mode' [default], 'n'/'nmodes' and 'all'/'modes'")
}
Поскольку он использует метод Ken для расчета частот, производительность также оптимизирована, используя AkselA post I, сравнивая некоторые из предыдущих ответов, чтобы показать, насколько моя функция близка к производительности в Ken, с условными значениями для разных вариантов вывода, вызывающих только незначительные накладные расходы:
Mode
найденной в пакете pracma
. Хотите объяснить?
Вот функция, чтобы найти режим:
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)
}
R имеет так много дополнительных пакетов, что некоторые из них могут обеспечить [статистический] режим числового списка/серии/вектора.
Однако стандартная библиотека R сама по себе не имеет такого встроенного метода! Один из способов обойти это - использовать некоторую конструкцию следующим образом (и превратить ее в функцию, если вы часто используете...):
mySamples <- c(19, 4, 5, 7, 29, 19, 29, 13, 25, 19)
tabSmpl<-tabulate(mySamples)
SmplMode<-which(tabSmpl== max(tabSmpl))
if(sum(tabSmpl == max(tabSmpl))>1) SmplMode<-NA
> SmplMode
[1] 19
Для большего списка образцов следует рассмотреть возможность использования временной переменной для значения max (tabSmpl) (я не знаю, что R автоматически оптимизирует это)
Ссылка: см. "Как насчет медианы и режима?" в этом Урок KickStarting R
Это, по-видимому, подтверждает, что (по крайней мере, на момент написания этого урока) в R нет функции режима (ну... mode(), как вы выяснили, используется для утверждения типа переменных).
Небольшая модификация ответа Кен Уильямса, добавляющая необязательные параметры na.rm
и return_multiple
.
В отличие от ответов, основанных на names()
, этот ответ поддерживает тип данных x
в возвращаемом значении (значениях).
stat_mode <- function(x, return_multiple = TRUE, na.rm = FALSE) {
if(na.rm){
x <- na.omit(x)
}
ux <- unique(x)
freq <- tabulate(match(x, ux))
mode_loc <- if(return_multiple) which(freq==max(freq)) else which.max(freq)
return(ux[mode_loc])
}
Чтобы показать, что он работает с необязательными параметрами и поддерживает тип данных:
foo <- c(2L, 2L, 3L, 4L, 4L, 5L, NA, NA)
bar <- c('mouse','mouse','dog','cat','cat','bird',NA,NA)
str(stat_mode(foo)) # int [1:3] 2 4 NA
str(stat_mode(bar)) # chr [1:3] "mouse" "cat" NA
str(stat_mode(bar, na.rm=T)) # chr [1:2] "mouse" "cat"
str(stat_mode(bar, return_mult=F, na.rm=T)) # chr "mouse"
Благодаря @Frank для упрощения.
Я просматривал все эти варианты и начал задаваться вопросом об их относительных функциях и характеристиках, поэтому я сделал несколько тестов. В случае, если кому-то еще интересны то же самое, я делюсь своими результатами здесь.
Не желая беспокоиться обо всех функциях, размещенных здесь, я решил сфокусироваться на выборке, основанном на нескольких критериях: функция должна работать как с символьными, так и с факториальными, логическими и числовыми векторами, она должна иметь дело с НС и другими проблемными значения должны быть "разумными", т.е. никакими числами в качестве характера или другой такой глупости.
Я также добавил функцию моего собственного, которая основана на той же идее rle
, что и chrispy's, кроме адаптированной для более общего использования:
library(magrittr)
Aksel <- function(x, freq=FALSE) {
z <- 2
if (freq) z <- 1:2
run <- x %>% as.vector %>% sort %>% rle %>% unclass %>% data.frame
colnames(run) <- c("freq", "value")
run[which(run$freq==max(run$freq)), z] %>% as.vector
}
set.seed(2)
F <- sample(c("yes", "no", "maybe", NA), 10, replace=TRUE) %>% factor
Aksel(F)
# [1] maybe yes
C <- sample(c("Steve", "Jane", "Jonas", "Petra"), 20, replace=TRUE)
Aksel(C, freq=TRUE)
# freq value
# 7 Steve
Я закончил работу с пятью функциями на двух наборах тестовых данных через microbenchmark
. Названия функций относятся к их соответствующим авторам:
Функция Chris была установлена на method="modes"
и na.rm=TRUE
по умолчанию, чтобы сделать ее более сопоставимой, но кроме того, что функции были использованы, как представлено здесь их авторами.
В скорости только одна версия Kens выигрывает, но она также является единственной из них, которая будет сообщать только один режим, независимо от того, сколько там действительно. Как это часто бывает, существует компромисс между скоростью и универсальностью. В method="mode"
версия Chris вернет значение, если есть один режим, иначе NA. Я думаю, что это приятный штрих.
Я также думаю, что интересно, как на некоторые функции влияет большее количество уникальных значений, в то время как другие - не так много. Я не изучил код подробно, чтобы выяснить, почему это, кроме устранения логического/числового в качестве причины.
Хотя мне нравится простая функция Кен Уильямса, я хотел бы получить несколько режимов, если они существуют. Имея это в виду, я использую следующую функцию, которая возвращает список режимов, если несколько или одиночный.
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)) )]
}
Это работает довольно хорошо
> a<-c(1,1,2,2,3,3,4,4,5)
> names(table(a))[table(a)==max(table(a))]
Другое возможное решение:
Mode <- function(x) {
if (is.numeric(x)) {
x_table <- table(x)
return(as.numeric(names(x_table)[which.max(x_table)]))
}
}
Использование:
set.seed(100)
v <- sample(x = 1:100, size = 1000000, replace = TRUE)
system.time(Mode(v))
Вывод:
user system elapsed
0.32 0.00 0.31
Я использовал бы функцию плотности() для определения сглаженного максимума (возможно непрерывного) распределения:
function(x) density(x, 2)$x[density(x, 2)$y == max(density(x, 2)$y)]
где x - сбор данных. Обратите внимание на настраиваемый пареметр функции плотности, который регулирует сглаживание.
Еще одна простая опция, которая дает все значения, упорядоченные по частоте, - это использовать rle
:
df = as.data.frame(unclass(rle(sort(mySamples))))
df = df[order(-df$lengths),]
head(df)
Ниже приведен код, который можно использовать для поиска режима векторной переменной в R.
a <- table([vector])
names(a[a==max(a)])
Режим вычисления в основном в случае фактор-переменной, тогда мы можем использовать
labels(table(HouseVotes84$V1)[as.numeric(labels(max(table(HouseVotes84$V1))))])
HouseVotes84 - это набор данных, доступный в пакете "mlbench".
он даст максимальное значение метки. его проще использовать встроенными функциями без записи функции.
Можно попробовать следующую функцию:
mode <- function(x){
y <- as.factor(x)
freq <- summary(y)
mode <- names(freq)[freq[names(freq)] == max(freq)]
as.numeric(mode)
}
Вы также можете рассчитать количество раз, когда экземпляр произошел в вашем наборе и найти максимальное число. например.
> 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
>
Извините, я могу считать это слишком простым, но разве это не делает работу? (в 1,3 секунды для значений 1E6 на моей машине):
t0 <- Sys.time()
summary(as.factor(round(rnorm(1e6), 2)))[1]
Sys.time()-t0
Вам просто нужно заменить "round (rnorm (1e6), 2)" на ваш вектор.
summary.factor
- все, что он делает, это оборачивает подход sort(table(...))
в другие ответы.
Простым способом вычисления MODE вектора 'v', содержащего дискретные значения, является:
names(sort(table(v)))[length(sort(table(v)))]
mode
таким же, какclass
функций?