Có một chức năng tích hợp để tìm chế độ?


392

Trong R, mean()median()là các hàm tiêu chuẩn thực hiện những gì bạn mong đợi. mode()cho bạn biết chế độ lưu trữ nội bộ của đối tượng, không phải giá trị xảy ra nhiều nhất trong đối số của nó. Nhưng có một chức năng thư viện tiêu chuẩn thực hiện chế độ thống kê cho một vectơ (hoặc danh sách) không?


4
Bạn cần làm rõ liệu dữ liệu của bạn là số nguyên, số, hệ số ...? Ước tính chế độ cho số sẽ khác nhau và sử dụng các khoảng. Xem chế độ
smci

2
Tại sao R không có chức năng tích hợp cho chế độ? Tại sao R coi modelà giống như hàm class?
Corey Levinson

Câu trả lời:


400

Thêm một giải pháp, hoạt động cho cả dữ liệu số & ký tự / yếu tố:

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

Trên chiếc máy nhỏ bé của tôi, nó có thể tạo và tìm chế độ của vectơ 10M trong khoảng nửa giây.

Nếu tập dữ liệu của bạn có thể có nhiều chế độ, giải pháp trên có cùng cách tiếp cận which.maxvà trả về giá trị xuất hiện đầu tiên của bộ chế độ. Để trả về tất cả các chế độ, hãy sử dụng biến thể này (từ @digEmAll trong phần bình luận):

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

7
Cũng hoạt động cho logic! Bảo tồn kiểu dữ liệu cho tất cả các loại vectơ (không giống như một số triển khai trong các câu trả lời khác).
DavidC

39
Điều này không trả về tất cả các chế độ trong trường hợp bộ dữ liệu đa phương thức (ví dụ c(1,1,2,2)). Bạn nên thay đổi dòng cuối cùng của mình với:tab <- tabulate(match(x, ux)); ux[tab == max(tab)]
digEmAll

6
@verybadatthis Vì điều đó, bạn sẽ thay thế ux[which.max(tabulate(match(x, ux)))]bằng chỉ max(tabulate(match(x, ux))).
Ken Williams

4
Bạn lưu ý rằng Mode(1:3)cho 1Mode(3:1)cho 3, vì vậy Chế độ trả về phần tử thường xuyên nhất hoặc phần tử đầu tiên nếu tất cả chúng là duy nhất.
Enrique Pérez Herrero

2
Như Enrique đã nói: Điều này thất bại khi không có chế độ, và thay vào đó cho bạn cảm giác rằng giá trị đầu tiên là chế độ. Sẽ tốt hơn nhiều nếu nó trở lại 0hoặc NAtrong những trường hợp đó.
not2qubit

66

Có gói modeestcung cấp các công cụ ước tính của chế độ dữ liệu đơn biến (và đôi khi là đa phương thức) và các giá trị của các chế độ phân phối xác suất thông thường.

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

Để biết thêm thông tin xem trang này


7
Vì vậy, để có được giá trị chế độ mfv(mySamples)[1],. Điều 1quan trọng là nó thực sự trả về giá trị s thường xuyên nhất .
nguyên tử

nó dường như không hoạt động trong ví dụ này: thư viện (chế độ) a <- rnorm (50, 30, 2) b <- rnorm (100, 35, 2) c <- rnorm (20, 37, 2) nhiệt độºC <- c (a, b, c) hist (nhiệt độ ºC) #mean abline (v = mean (nhiệt độ ºC), col = "đỏ", lwd = 2) #median abline (v = median (nhiệt độ ºC), col = "đen", lwd = 2) #mode abline (v = mlv (nhiệt độ CC, phương thức = "mfv") [1], col = "cam", lwd = 2)
Agus camacho

1
@atomicules: với [1] bạn chỉ nhận được chế độ đầu tiên. Đối với phân phối n-modal bimodal hoặc chung, bạn sẽ chỉ cầnmfv(mySamples)
petzi

1
Đối với phiên bản R 3.6.0, nó cho biết chức năng 'không thể tìm thấy chức năng "mlv"' và lỗi tương tự khi tôi thử mfv (mysamples). Có mất giá không?
Bác sĩ Nisha Arora

@DrNishaArora: Bạn đã tải xuống gói 'modeest' chưa?
petzi

59

tìm thấy cái này trong danh sách gửi thư r, hy vọng nó hữu ích. Đó cũng là những gì tôi đã suy nghĩ. Bạn sẽ muốn bảng () dữ liệu, sắp xếp và sau đó chọn tên. Đó là hackish nhưng nên làm việc.

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

6
Đó là một công việc thông minh xung quanh là tốt. Nó có một vài nhược điểm: thuật toán sắp xếp có thể tốn nhiều không gian và thời gian hơn so với các cách tiếp cận dựa trên max () (=> cần tránh cho các danh sách mẫu lớn hơn). Ngoài ra, ouput là của chế độ (bỏ qua cách chơi chữ / sự mơ hồ) "ký tự" chứ không phải "số". Và, tất nhiên, nhu cầu kiểm tra phân phối đa phương thức thường sẽ yêu cầu lưu trữ bảng đã sắp xếp để tránh làm hỏng nó một lần nữa.
mjv

2
Tôi đã đo thời gian chạy với hệ số 1e6 và giải pháp này nhanh hơn câu trả lời được chấp nhận bởi gần như là 3 yếu tố!
vonjd

Tôi chỉ chuyển đổi nó thành số bằng cách sử dụng as.numeric (). Hoạt động hoàn toàn tốt. Cảm ơn bạn!
Abhishek Singh

47

Tôi thấy bài viết của Ken Williams ở trên là tuyệt vời, tôi đã thêm một vài dòng vào tài khoản cho các giá trị NA và biến nó thành một chức năng cho dễ dàng.

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

Tôi đã tìm thấy một vài cách tăng tốc cho điều này, xem câu trả lời dưới đây.
Dan Houghton

33

Một cách nhanh chóng và bẩn để ước tính chế độ của một vectơ số mà bạn tin rằng đến từ phân phối đơn biến liên tục (ví dụ: phân phối bình thường) đang xác định và sử dụng hàm sau:

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

Sau đó, để có được ước tính chế độ:

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

3
Chỉ cần một lưu ý về điều này: bạn có thể nhận được "chế độ" của bất kỳ nhóm số liên tục nào theo cách này. Dữ liệu không cần phải đến từ một phân phối bình thường để làm việc. Dưới đây là một ví dụ lấy số từ một phân phối thống nhất. 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 Thông báo lỗi đó cho bạn biết mọi thứ bạn cần biết. Nếu bạn chỉ có một điểm, bạn cần đặt băng thông theo cách thủ công khi gọi density. Tuy nhiên, nếu bạn chỉ có một datapoint thì giá trị của datapoint đó có thể sẽ là dự đoán tốt nhất của bạn cho chế độ này ...
Rasmus Bååth 10/2/2016

Bạn nói đúng, nhưng tôi chỉ thêm một điều chỉnh: estimate_mode <- function(x) { if (length(x)>1){ d <- density(x) d$x[which.max(d$y)] }else{ x } } Tôi đang thử nghiệm phương pháp để ước tính gió hướng chiếm ưu thế, thay vì trung bình của hướng sử dụng trung bình véc tơ với gói tròn. Tôi ', làm việc với các điểm trên một lớp đa giác, vì vậy, đôi khi chỉ có một điểm có hướng. Cảm ơn!
Sergio

@xhie Nghe có vẻ hợp lý :)
Rasmus Bååth

14

Các chức năng sau đây có ba hình thức:

method = "mode" [default]: tính toán chế độ cho một vectơ không
theo phương thức , khác trả về một phương thức NA = "nmodes": tính toán số lượng chế độ trong
phương thức vectơ = "chế độ": liệt kê tất cả các chế độ cho một phương thức không chính thống hoặc đa hình vectơ

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

Trong phần mô tả của bạn về các chức năng này, bạn đã hoán đổi "chế độ" và "bước sóng". Xem mã. Trên thực tế, "nmodes" trả về vectơ của các giá trị và "chế độ" trả về số lượng chế độ. Dù sao chức năng của bạn là linh hồn tốt nhất để tìm các chế độ tôi đã thấy cho đến nay.
Grzegorz Adam Kowalski

Rất cám ơn cho nhận xét. "nmode" và "mode" bây giờ sẽ hoạt động như mong đợi.
Chris

Hàm của bạn hoạt động gần như, ngoại trừ khi mỗi giá trị xảy ra thường xuyên sử dụng method = 'modes'. Sau đó, hàm trả về tất cả các giá trị duy nhất, tuy nhiên thực tế không có chế độ nào nên nó sẽ trả về NA. Tôi sẽ thêm một câu trả lời khác chứa một phiên bản tối ưu hóa chức năng của bạn, cảm ơn vì nguồn cảm hứng!
hugovdberg

Lần duy nhất một vectơ số không trống thường tạo ra NA với hàm này là khi sử dụng phương thức mặc định trên vectơ đa hình. Chế độ của một chuỗi số đơn giản như 1,2,3,4 thực sự là tất cả các số đó trong chuỗi, do đó, đối với các chuỗi tương tự, "chế độ" hoạt động như mong đợi. ví dụ: modeave (c (1,2,3,4), method = "mode") trả về [1] 1 2 3 4 Bất kể điều này, tôi rất muốn thấy chức năng được tối ưu hóa vì nó khá tốn tài nguyên trạng thái hiện tại
Chris

Để có phiên bản hiệu quả hơn của chức năng này, hãy xem bài đăng của @ hugovdberg ở trên :)
Chris

10

Đây, một giải pháp khác:

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

Bạn có thể thay thế dòng đầu tiên bằng bảng.
Jonathan Chang

Tôi đã nghĩ rằng 'tapply' hiệu quả hơn 'bảng', nhưng cả hai đều sử dụng vòng lặp for. Tôi nghĩ rằng giải pháp với bảng là tương đương. Tôi cập nhật câu trả lời.
teucer

9

Tôi chưa thể bỏ phiếu nhưng câu trả lời của Rasmus Bååth là điều tôi đang tìm kiếm. Tuy nhiên, tôi sẽ sửa đổi nó một chút cho phép hạn chế phân phối, ví dụ giá trị fro chỉ trong khoảng từ 0 đến 1.

estimate_mode <- function(x,from=min(x), to=max(x)) {
  d <- density(x, from=from, to=to)
  d$x[which.max(d$y)]
}

Chúng tôi biết rằng bạn có thể không muốn ràng buộc tất cả phân phối của mình, sau đó đặt từ = - "SỐ LỚN", thành = "SỐ LỚN"


error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
Sergio

x nên là một vectơ
AleRuete

8

Một sửa đổi nhỏ cho câu trả lời của Ken Williams, thêm thông số tùy chọn na.rmreturn_multiple .

Không giống như các câu trả lời dựa vào names(), câu trả lời này duy trì kiểu dữ liệu xtrong (các) giá trị được trả về.

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

Để hiển thị nó hoạt động với các thông số tùy chọn và duy trì kiểu dữ liệu:

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"

Cảm ơn @Frank đã đơn giản hóa.


7

Tôi đã viết đoạn mã sau để tạo chế độ.

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

Hãy thử nó:

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

6

Dựa trên chức năng của @ Chris để tính toán chế độ hoặc các số liệu liên quan, tuy nhiên, sử dụng phương pháp của Ken Williams để tính tần số. Điều này cung cấp một sửa chữa cho trường hợp không có chế độ nào cả (tất cả các yếu tố thường xuyên như nhau) và một số methodtên dễ đọc hơn .

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

Vì nó sử dụng phương pháp của Ken để tính toán tần số, hiệu suất cũng được tối ưu hóa, sử dụng bài đăng của AkselA, tôi đã điểm chuẩn một số câu trả lời trước đó để cho thấy chức năng của tôi gần với hiệu suất của Ken như thế nào, với các điều kiện cho các tùy chọn khác nhau chỉ gây ra chi phí nhỏ: So sánh các chức năng Chế độ


Mã bạn trình bày dường như là một bản sao thẳng hoặc ít hơn của Modehàm được tìm thấy trong pracmagói. Quan tâm để giải thích?
AkselA

Có thật không? Rõ ràng tôi không phải là người duy nhất nghĩ rằng đây là một cách tốt để tính toán Chế độ, nhưng tôi thực sự không biết điều đó (chưa bao giờ biết gói đó trước đây). Tôi đã làm sạch chức năng của Chris và cải thiện nó bằng cách tận dụng phiên bản của Ken và nếu nó giống với mã của người khác hoàn toàn là ngẫu nhiên.
hugovdberg

Tôi đã xem xét nó ngay bây giờ, nhưng pracmabạn tham khảo phiên bản nào của gói? Phiên bản 1.9.3 có cách triển khai hoàn toàn khác xa như tôi có thể thấy.
hugovdberg

2
Đẹp sửa đổi chức năng. Sau khi đọc thêm, tôi đã đưa ra kết luận rằng không có sự đồng thuận nào về việc phân phối đồng đều hay đơn âm có các nút, một số nguồn nói rằng danh sách các chế độ là bản phân phối, một số khác cho rằng không có nút. Thỏa thuận duy nhất là việc tạo ra một danh sách các chế độ cho các bản phân phối như vậy không có nhiều thông tin cũng như đặc biệt có ý nghĩa. NẾU bạn muốn chức năng trên tạo ra các chế độ như vậy, sau đó xóa dòng: nmodes <- ifelse (nmodes == n, 0L, nmodes)
Chris

1
@greendiod xin lỗi, tôi đã bỏ lỡ bình luận của bạn. Nó có sẵn thông qua ý chính này: gist.github.com/Hugovdberg/0f00444d46efd99ed27bbe227bdc4d37
hugovdberg

6

Hack này nên hoạt động tốt. Cung cấp cho bạn giá trị cũng như số lượng chế độ:

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

3

R có rất nhiều gói bổ trợ mà một số trong số chúng có thể cung cấp chế độ [thống kê] của danh sách / chuỗi / vectơ số.

Tuy nhiên, thư viện chuẩn của R dường như không có phương thức tích hợp như vậy! Một cách để giải quyết vấn đề này là sử dụng một số cấu trúc như sau (và để biến nó thành một hàm nếu bạn sử dụng thường xuyên ...):

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

Đối với danh sách mẫu lớn hơn, người ta nên cân nhắc sử dụng biến tạm thời cho giá trị tối đa (tabSmpl) (Tôi không biết rằng R sẽ tự động tối ưu hóa điều này)

Tham khảo: xem "Làm thế nào về trung vị và chế độ?" trong bài học KickStarting R
này dường như xác nhận rằng (ít nhất là khi viết bài học này) không có chức năng chế độ trong R (well ... mode () như bạn phát hiện ra được sử dụng để khẳng định loại biến ).


3

Điều này hoạt động khá tốt

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

3

Đây là một chức năng để tìm chế độ:

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

3

Dưới đây là mã có thể được sử dụng để tìm chế độ của biến vector trong R.

a <- table([vector])

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

3

Có nhiều giải pháp được cung cấp cho cái này. Tôi đã kiểm tra cái đầu tiên và sau đó tự viết. Đăng nó ở đây nếu nó giúp bất cứ ai:

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

Hãy thử nghiệm nó với một vài ví dụ. Tôi đang lấy tập irisdữ liệu. Cho phép kiểm tra với dữ liệu số

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

mà bạn có thể xác minh là chính xác.

Bây giờ, trường không số duy nhất trong bộ dữ liệu iris (Loài) không có chế độ. Hãy thử nghiệm với ví dụ của chúng ta

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

BIÊN TẬP

Như đã đề cập trong các bình luận, người dùng có thể muốn duy trì loại đầu vào. Trong trường hợp đó, chức năng chế độ có thể được sửa đổi thành:

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

Dòng cuối cùng của hàm chỉ đơn giản là ép giá trị chế độ cuối cùng với kiểu của đầu vào ban đầu.


Điều này trả về một yếu tố, trong khi người dùng có thể muốn duy trì loại đầu vào. Có thể thêm một bước giữay[,1] <- sort(unique(x))
Frank

2

Tôi sẽ sử dụng hàm mật độ () để xác định mức tối đa được làm mịn của phân phối (có thể liên tục):

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

Trong đó x là tập hợp dữ liệu. Hãy chú ý đến các paremeter điều chỉnh của hàm mật độ điều chỉnh sự làm mịn.


2

Mặc dù tôi thích chức năng đơn giản của Ken Williams, tôi muốn truy xuất nhiều chế độ nếu chúng tồn tại. Với ý nghĩ đó, tôi sử dụng chức năng sau đây trả về danh sách các chế độ nếu nhiều hoặc đơn.

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

Sẽ phù hợp hơn cho việc sử dụng theo chương trình nếu nó luôn trả về một danh sách - có độ dài 1 nếu chỉ có một chế độ
asac

Đó là một điểm hợp lệ @ antoine-sac. Điều tôi thích về giải pháp này là vectơ được trả về để lại câu trả lời dễ dàng. Đơn giản chỉ cần giải quyết đầu ra của hàm: r <- mode (c (2, 2, 3, 3)) với các chế độ có sẵn tại r [1] và r [2]. Tuy nhiên, bạn làm cho một điểm tốt !!
RandallShanePhD

Chính xác, đây là nơi giải pháp của bạn thiếu. Nếu modetrả về một danh sách có nhiều giá trị, thì r [1] không phải là giá trị đầu tiên; thay vào đó là danh sách độ dài 1 chứa giá trị đầu tiên và bạn phải thực hiện r [[1]] để có chế độ đầu tiên dưới dạng số chứ không phải danh sách. Bây giờ khi có một chế độ duy nhất, r của bạn không phải là một danh sách nên r [1] hoạt động, đó là lý do tại sao tôi nghĩ rằng nó không nhất quán. Nhưng vì r [[1]] cũng hoạt động khi r là một vectơ đơn giản, nên thực sự có một sự nhất quán mà tôi đã nhận ra ở chỗ bạn luôn có thể sử dụng [[để truy cập các phần tử.
asac

2

Tôi đã xem qua tất cả các tùy chọn này và bắt đầu tự hỏi về các tính năng và hiệu suất tương đối của chúng, vì vậy tôi đã thực hiện một số thử nghiệm. Trong trường hợp bất kỳ ai khác tò mò về điều tương tự, tôi sẽ chia sẻ kết quả của mình ở đây.

Không muốn bận tâm về tất cả các hàm được đăng ở đây, tôi đã chọn tập trung vào một mẫu dựa trên một vài tiêu chí: hàm phải hoạt động trên cả vectơ ký tự, yếu tố, logic và số, nên xử lý NA và các giá trị có vấn đề khác một cách thích hợp, và đầu ra phải là "hợp lý", tức là không có số nào là ký tự hoặc độ silliness khác.

Tôi cũng đã thêm một chức năng của riêng mình, dựa trên rleý tưởng tương tự như chrispy, ngoại trừ điều chỉnh cho sử dụng chung hơn:

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

Cuối cùng tôi đã chạy năm chức năng, trên hai bộ dữ liệu thử nghiệm microbenchmark. Các tên hàm đề cập đến các tác giả tương ứng của họ:

nhập mô tả hình ảnh ở đây

Chức năng của Chris đã được đặt thành method="modes"na.rm=TRUE theo mặc định để làm cho nó có thể so sánh hơn, nhưng ngoài chức năng đó được sử dụng như được trình bày ở đây bởi các tác giả của họ.

Về vấn đề tốc độ, một mình phiên bản Zack chiến thắng một cách khéo léo, nhưng đây cũng là phiên bản duy nhất trong số này sẽ chỉ báo cáo một chế độ, bất kể có bao nhiêu thực sự có. Như thường lệ, có một sự đánh đổi giữa tốc độ và tính linh hoạt. Trongmethod="mode" , phiên bản của Chris sẽ trả về một giá trị nếu có một chế độ, NA khác. Tôi nghĩ đó là một liên lạc tốt đẹp. Tôi cũng nghĩ thật thú vị khi một số chức năng bị ảnh hưởng bởi số lượng giá trị duy nhất tăng lên, trong khi những chức năng khác không nhiều như vậy. Tôi đã không nghiên cứu chi tiết mã để tìm hiểu lý do tại sao, ngoài việc loại bỏ logic / số là nguyên nhân.


2

Chế độ không thể hữu ích trong mọi tình huống. Vì vậy, chức năng nên giải quyết tình huống này. Hãy thử các chức năng sau.

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

Đầu ra,

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

Xin lỗi, tôi chỉ không thấy làm thế nào điều này thêm bất cứ điều gì mới vào những gì đã được đăng. Ngoài ra, đầu ra của bạn có vẻ không phù hợp với chức năng của bạn ở trên.
not2qubit

2

Điều này dựa trên câu trả lời của jprockbelly, bằng cách thêm tốc độ cho các vectơ rất ngắn. Điều này hữu ích khi áp dụng chế độ cho data.frame hoặc có thể truy cập được với nhiều nhóm nhỏ:

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

1

Một tùy chọn đơn giản khác cung cấp tất cả các giá trị được sắp xếp theo tần số là sử dụng rle:

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

1

Một giải pháp khả thi khác:

Mode <- function(x) {
    if (is.numeric(x)) {
        x_table <- table(x)
        return(as.numeric(names(x_table)[which.max(x_table)]))
    }
}

Sử dụng:

set.seed(100)
v <- sample(x = 1:100, size = 1000000, replace = TRUE)
system.time(Mode(v))

Đầu ra:

   user  system elapsed 
   0.32    0.00    0.31 

1

Tôi nghĩ rằng các quan sát của bạn là các lớp từ các số thực và bạn hy vọng rằng chế độ là 2,5 khi các quan sát của bạn là 2, 2, 3 và 3 thì bạn có thể ước tính chế độ mode = l1 + i * (f1-f0) / (2f1 - f0 - f2)trong đó l1 .. giới hạn thấp hơn của lớp thường xuyên nhất, F1 . .frequency của lớp thường xuyên nhất, f0 ..frequency của các lớp trước lớp thường xuyên nhất, f2 ..frequency của các lớp sau lớp thường xuyên nhất và i ..Class khoảng thời gian như được đưa ra, ví dụ như trong 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

Trong trường hợp bạn muốn cấp độ thường xuyên nhất và bạn có nhiều cấp độ thường xuyên nhất, bạn có thể nhận được tất cả các cấp độ đó, ví dụ:

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

1

Thêm một cách tiếp cận dữ liệu có thể.

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

1

Dưới đây là một số cách bạn có thể thực hiện trong thời gian chạy 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))

0

Có thể thử chức năng sau:

  1. biến đổi giá trị số thành yếu tố
  2. sử dụng tóm tắt () để đạt được bảng tần số
  3. chế độ trả về chỉ số có tần số lớn nhất
  4. biến đổi hệ số trở lại số thậm chí có nhiều hơn 1 chế độ, chức năng này hoạt động tốt!
mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}

0

Chế độ tính toán chủ yếu là trong trường hợp biến nhân tố thì chúng ta có thể sử dụng

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

HouseVotes84 là bộ dữ liệu có sẵn trong gói 'mlbench'.

nó sẽ cho giá trị nhãn tối đa. nó dễ sử dụng hơn bởi các hàm sẵn có mà không cần chức năng ghi.


0

Dường như với tôi rằng nếu một bộ sưu tập có chế độ, thì các phần tử của nó có thể được ánh xạ một-một với các số tự nhiên. Vì vậy, vấn đề tìm chế độ giảm xuống để tạo ra ánh xạ như vậy, tìm chế độ của các giá trị được ánh xạ, sau đó ánh xạ trở lại một số mục trong bộ sưu tập. (Xử lýNA xảy ra ở giai đoạn ánh xạ).

Tôi có một histogramchức năng hoạt động trên một hiệu trưởng tương tự. (Các chức năng đặc biệt và khai thác sử dụng trong mã được trình bày trong tài liệu này cần được xác định trong Shapiro và / hoặc neatOveRse Các phần của Shapiro và neatOveRse nhân đôi ở đây là như vậy lặp lại với sự cho phép;. Các đoạn trùng lặp có thể được sử dụng theo các điều khoản của trang web này. ) Mã giả cho R histogram

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

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

(Các toán tử nhị phân đặc biệt thực hiện đường ống , curryingthành phần ) Tôi cũng có một maxlochàm, tương tự which.max, nhưng trả về tất cả các cực đại tuyệt đối của một vectơ. Mã giả cho R maxloc

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

Sau đó

imode <- histogram %O% maxloc

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

sẽ tính toán chế độ của bất kỳ bộ sưu tập nào, được cung cấp các maphàm -ping và -ping thích hợp unmapđược xác định.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.