Есть ли встроенная функция для поиска режима?

В R, mean() и median() - стандартные функции, которые делают то, что вы ожидаете. mode() указывает режим внутреннего хранения объекта, а не значение, которое больше всего встречается в его аргументе. Но существует ли стандартная библиотечная функция, которая реализует статистический режим для вектора (или списка)?

Ответ 1

Еще одно решение, которое работает как для числовых, так и для символьных/факторных данных:

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

На моей маленькой маленькой машине, которая может генерировать и находить режим вектора 10 М-целого примерно через полсекунды.

Ответ 2

Существует пакет 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")

Для получения дополнительной информации см. эту страницу

Ответ 3

нашел это в списке рассылки r, надеюсь, что это будет полезно. Это то, о чем я и думал. Вам нужно будет таблицы() данных, сортировки, а затем выбрать первое имя. Он взламывает, но должен работать.

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

Ответ 4

Я нашел пост Кен Уильямса выше, я добавил несколько строк для учета значений 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)))])
}

Ответ 5

Быстрый и грязный способ оценки режима вектора чисел, который, по вашему мнению, поступает из непрерывного одномерного распределения (например, нормального распределения), определяет и использует следующую функцию:

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

Ответ 6

Следующая функция имеет три формы:

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

Ответ 7

Здесь другое решение:

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

Ответ 8

Я не могу голосовать, но ответ 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)]
}

Мы знаем, что вы можете не захотеть ограничить вообще свой дистрибутив, а затем установить из = - "БОЛЬШОЙ НОМЕР", чтобы = "БОЛЬШОЙ НОМЕР"

Ответ 9

Я написал следующий код для создания режима.

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)

Ответ 10

На основе функции @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, с условными значениями для разных вариантов вывода, вызывающих только незначительные накладные расходы: Сравнение функций режима

Ответ 11

Этот хак должен работать нормально. Дает вам значение, а также счетчик режима:

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

Ответ 12

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(), как вы выяснили, используется для утверждения типа переменных).

Ответ 13

Вот функция, чтобы найти режим:

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

Ответ 14

Это работает довольно хорошо

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

Ответ 15

Хотя мне нравится простая функция Кен Уильямса, я хотел бы получить несколько режимов, если они существуют. Имея это в виду, я использую следующую функцию, которая возвращает список режимов, если несколько или одиночный.

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

Ответ 16

Я просматривал все эти варианты и начал задаваться вопросом об их относительных функциях и характеристиках, поэтому я сделал несколько тестов. В случае, если кому-то еще интересны то же самое, я делюсь своими результатами здесь.

Не желая беспокоиться обо всех функциях, размещенных здесь, я решил сфокусироваться на выборке, основанном на нескольких критериях: функция должна работать как с символьными, так и с факториальными, логическими и числовыми векторами, она должна иметь дело с НС и другими проблемными значения должны быть "разумными", т.е. никакими числами в качестве характера или другой такой глупости.

Я также добавил функцию моего собственного, которая основана на той же идее 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. Я думаю, что это приятный штрих. Я также думаю, что интересно, как на некоторые функции влияет большее количество уникальных значений, в то время как другие - не так много. Я не изучил код подробно, чтобы выяснить, почему это, кроме устранения логического/числового в качестве причины.

Ответ 17

Небольшая модификация ответа Кен Уильямса, добавляющая необязательные параметры 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 для упрощения.

Ответ 18

Еще одна простая опция, которая дает все значения, упорядоченные по частоте, - это использовать rle:

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

Ответ 19

Я использовал бы функцию плотности() для определения сглаженного максимума (возможно непрерывного) распределения:

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

где x - сбор данных. Обратите внимание на настраиваемый пареметр функции плотности, который регулирует сглаживание.

Ответ 20

Другое возможное решение:

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 

Ответ 21

Извините, я могу считать это слишком простым, но разве это не делает работу? (в 1,3 секунды для значений 1E6 на моей машине):

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

Вам просто нужно заменить "round (rnorm (1e6), 2)" на ваш вектор.

Ответ 22

Вы также можете рассчитать количество раз, когда экземпляр произошел в вашем наборе и найти максимальное число. например.

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

Ответ 23

Можно попробовать следующую функцию:

  • преобразует числовые значения в коэффициент
  • используйте summary() для получения таблицы частот
  • режим возврата индекс, частота которого является наибольшей
  • преобразует коэффициент обратно в числовое, даже существует более одного режима, эта функция работает хорошо!
mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}

Ответ 24

Режим вычисления в основном в случае фактор-переменной, тогда мы можем использовать

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

HouseVotes84 - это набор данных, доступный в пакете "mlbench".

он даст максимальное значение метки. его проще использовать встроенными функциями без записи функции.

Ответ 25

Ниже приведен код, который можно использовать для поиска режима векторной переменной в R.

a <- table([vector])

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

Ответ 26

Простым способом вычисления MODE вектора 'v', содержащего дискретные значения, является:

names(sort(table(v)))[length(sort(table(v)))]