มีฟังก์ชันในตัวสำหรับค้นหาโหมดหรือไม่


392

ใน R mean()และmedian()เป็นฟังก์ชั่นมาตรฐานที่ทำในสิ่งที่คุณคาดหวัง mode()บอกโหมดการเก็บข้อมูลภายในของวัตถุไม่ใช่ค่าที่เกิดขึ้นมากที่สุดในการโต้แย้ง แต่มีฟังก์ชันไลบรารีมาตรฐานที่ใช้โหมดสถิติสำหรับเวกเตอร์ (หรือรายการ) หรือไม่?


4
คุณต้องชี้แจงว่าข้อมูลของคุณเป็นจำนวนเต็มตัวเลขปัจจัย ... หรือไม่ การประมาณโหมดสำหรับตัวเลขจะแตกต่างกันและใช้ช่วงเวลา ดูโหมด
smci

2
ทำไม R ไม่มีฟังก์ชั่นในตัวสำหรับโหมด? ทำไม R พิจารณาmodeที่จะเป็นเช่นเดียวกับฟังก์ชั่นclass?
คอเรย์เลวินสัน

คำตอบ:


400

อีกหนึ่งโซลูชันที่ใช้งานได้ทั้งข้อมูลตัวเลขและตัวละคร / ปัจจัย:

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

บนเครื่องเล็ก ๆ น้อย ๆ ของฉันที่สามารถสร้าง & หาโหมดของเวกเตอร์จำนวนเต็ม 10M ในเวลาประมาณครึ่งวินาที

หากชุดข้อมูลของคุณอาจมีหลายโหมดการแก้ปัญหาข้างต้นใช้แนวทางเดียวกับwhich.maxและส่งกลับค่าที่ปรากฏครั้งแรกของชุดโหมด หากต้องการส่งคืนโหมดทั้งหมดให้ใช้ตัวแปรนี้ (จาก @digEmAll ในความคิดเห็น):

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

7
ยังใช้งานได้กับตรรกะ! เก็บรักษาชนิดข้อมูลของเวกเตอร์ทุกประเภท (ไม่เหมือนกับการนำไปใช้งานบางอย่างในคำตอบอื่น)
DavidC

39
สิ่งนี้จะไม่ส่งคืนโหมดทั้งหมดในกรณีของชุดข้อมูลแบบหลายโหมด (เช่นc(1,1,2,2)) คุณควรเปลี่ยนบรรทัดสุดท้ายด้วย:tab <- tabulate(match(x, ux)); ux[tab == max(tab)]
digEmAll

6
@verybadatthis เพื่อที่คุณจะเข้ามาแทนที่ที่มีเพียงux[which.max(tabulate(match(x, ux)))] max(tabulate(match(x, ux)))
เคนวิลเลียมส์

4
คุณทราบว่าMode(1:3)ให้1และMode(3:1)ให้3ดังนั้นโหมดจะส่งคืนองค์ประกอบที่พบบ่อยที่สุดหรือองค์ประกอบแรกหากองค์ประกอบทั้งหมดนั้นไม่ซ้ำ
Enrique Pérez Herrero

2
ดังที่ Enrique กล่าวว่า: สิ่งนี้จะล้มเหลวเมื่อไม่มีโหมดและให้ความประทับใจว่าค่าแรกคือโหมด คงจะดีกว่านี้ถ้ามันกลับมา0หรือNAในกรณีเหล่านั้น
not2qubit

66

มีแพ็กเกจmodeestที่ให้การประมาณค่าของโหมด univariate unimodal (และบางครั้งต่อเนื่อง) ข้อมูลและค่าของโหมดของการแจกแจงความน่าจะเป็นปกติ

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

สำหรับข้อมูลเพิ่มเติมดูหน้านี้


7
ดังนั้นเพื่อให้ได้ค่าโหมด, mfv(mySamples)[1]. 1เป็นสิ่งสำคัญที่จะส่งกลับจริงมากที่สุดมูลค่าบ่อยs
atomicules

ดูเหมือนว่าจะไม่ทำงานในตัวอย่างนี้: library (modeest) a <- rnorm (50, 30, 2) b <- rnorm (100, 35, 2) c <- rnorm (20, 37, 2) อุณหภูมิºC <- c (a, b, c) hist (อุณหภูมิºC) #mean abline (v = หมายถึง (อุณหภูมิºC), col = "สีแดง", lwd = 2) #median abline (v = ค่ามัธยฐาน (อุณหภูมิºC), col = "สีดำ", lwd = 2) #mode abline (v = mlv (อุณหภูมิºC, วิธีการ = "mfv") [1], col = "orange", lwd = 2)
Agus camacho

1
@atomicules: ด้วย [1] คุณจะได้รับโหมดแรกเท่านั้น สำหรับการกระจาย bimodal หรือทั่วไป n-modal คุณจะต้องเพียงmfv(mySamples)
petzi

1
สำหรับรุ่น R 3.6.0 มันบอกว่าฟังก์ชั่น 'ไม่สามารถหาฟังก์ชั่น "mlv"' และข้อผิดพลาดเดียวกันเมื่อฉันพยายาม mfv (mysamples) คิดค่าเสื่อมราคาหรือไม่
Dr Nisha Arora

@DrNishaArora: คุณดาวน์โหลดแพ็คเกจ 'modeest' หรือไม่
petzi

59

พบสิ่งนี้ในรายการส่งเมล r หวังว่าจะเป็นประโยชน์ มันเป็นสิ่งที่ฉันคิดอยู่แล้ว คุณจะต้องการตาราง () ข้อมูลเรียงลำดับแล้วเลือกชื่อ มันแฮ็ก แต่ควรจะทำงาน

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

6
นั่นเป็นวิธีที่ฉลาดเช่นกัน มีข้อบกพร่องเล็กน้อย: อัลกอริทึมการเรียงลำดับอาจใช้พื้นที่และเวลามากกว่าวิธีการตาม ((>> ที่ควรหลีกเลี่ยงสำหรับรายการตัวอย่างขนาดใหญ่) ouput ยังเป็นของโหมด (อภัยโทษปุน / ความกำกวม) "ตัวละคร" ไม่ "ตัวเลข" และแน่นอนว่าความจำเป็นในการทดสอบการกระจายหลายโหมดมักจะต้องการการจัดเก็บตารางที่เรียงลำดับเพื่อหลีกเลี่ยงการบีบอัดใหม่อีกครั้ง
mjv

2
ฉันวัดเวลาทำงานด้วยองค์ประกอบ 1e6 และวิธีนี้เร็วกว่าคำตอบที่ได้รับการยอมรับจากปัจจัยเกือบ 3!
vonjd

ฉันเพิ่งแปลงเป็นตัวเลขโดยใช้ as.numeric () ทำงานได้ดีอย่างสมบูรณ์ ขอบคุณ!
Abhishek Singh

47

ฉันพบว่า Ken Williams โพสต์ด้านบนนั้นยอดเยี่ยมฉันเพิ่มสองสามบรรทัดเพื่ออธิบายค่า 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)))])
}

ฉันพบความเร็วสองสามอย่างสำหรับสิ่งนี้ดูคำตอบด้านล่าง
Dan Houghton

33

วิธีที่รวดเร็วและสกปรกในการประเมินโหมดของเวกเตอร์ของตัวเลขที่คุณเชื่อว่ามาจากการแจกแจงแบบไม่มีตัวแปรต่อเนื่อง (เช่นการแจกแจงแบบปกติ) กำลังกำหนดและใช้ฟังก์ชันต่อไปนี้:

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

3
เพียงแค่ทราบเกี่ยวกับสิ่งนี้: คุณสามารถรับ "โหมด" ของกลุ่มใด ๆ ของตัวเลขต่อเนื่องด้วยวิธีนี้ ข้อมูลไม่จำเป็นต้องมาจากการแจกแจงแบบปกติเพื่อให้ทำงานได้ นี่คือตัวอย่างการจดตัวเลขจากการแจกแจงแบบ 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 ข้อความผิดพลาดบอกทุกสิ่งที่คุณจำเป็นต้องรู้ densityหากคุณเพียงแค่มีจุดหนึ่งที่คุณต้องตั้งค่าแบนด์วิดธ์ด้วยตนเองเมื่อโทร อย่างไรก็ตามถ้าคุณมีดาต้าพอยน์เพียงอันเดียวค่าของดาต้าพอยน์นั้นน่าจะเป็นคำตอบที่ดีที่สุดสำหรับโหมดต่อไป ...
Rasmus Bååth

คุณพูดถูก แต่ฉันเพิ่มแค่บิดเดียว: estimate_mode <- function(x) { if (length(x)>1){ d <- density(x) d$x[which.max(d$y)] }else{ x } } ฉันกำลังทดสอบวิธีการประมาณทิศทางลมที่เด่นกว่าแทนที่จะใช้ทิศทางเฉลี่ยโดยใช้เวกเตอร์เฉลี่ยกับแพ็คเกจวงกลม ฉันทำงานกับคะแนนเหนือรูปหลายเหลี่ยมดังนั้นบางครั้งก็มีเพียงจุดเดียวที่มีทิศทาง ขอบคุณ!
Sergio

@xhie ฟังดูสมเหตุสมผล :)
Rasmus Bååth

14

ฟังก์ชั่นต่อไปนี้มาในสามรูปแบบ:

method = "mode" [default]: คำนวณโหมดสำหรับเวกเตอร์ unimodal มิฉะนั้นจะคืนค่า NA
method = "nmodes": คำนวณจำนวนโหมดใน vector
method = "modes": แสดงรายการโหมดทั้งหมดสำหรับ unimodal หรือ polymodal เวกเตอร์

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

ในคำอธิบายของคุณของฟังก์ชั่นนี้คุณสลับ "โหมด" และ "nmodes" ดูรหัส ที่จริงแล้ว "nmodes" จะคืนค่าเวกเตอร์ของค่าและ "โหมด" จะคืนค่าจำนวนโหมด ไม่เคยมีฟังก์ชั่นของคุณมาจาก soultion ที่ดีที่สุดในการค้นหาโหมดที่ฉันเคยเห็น
Grzegorz Adam Kowalski

ขอบคุณมากสำหรับการแสดงความคิดเห็น. "nmode" และ "โหมด" ควรทำงานได้ตามที่คาดไว้
Chris

method = 'modes'ฟังก์ชั่นการทำงานของเกือบยกเว้นเมื่อแต่ละค่าเท่าเทียมกันเกิดขึ้นมักจะใช้ จากนั้นฟังก์ชั่นจะคืนค่าที่ไม่ซ้ำกันทั้งหมด แต่จริงๆแล้วไม่มีโหมดดังนั้นจึงควรส่งคืนNAแทน ฉันจะเพิ่มคำตอบอีกอันที่มีฟังก์ชั่นเวอร์ชั่นที่ได้รับการปรับปรุงเล็กน้อยของคุณขอบคุณสำหรับแรงบันดาลใจ!
hugovdberg

ครั้งเดียวที่เวกเตอร์ตัวเลขที่ไม่ว่างเปล่าโดยปกติควรสร้าง NA ด้วยฟังก์ชันนี้คือเมื่อใช้วิธีการเริ่มต้นกับเวกเตอร์ polymodal โหมดของลำดับของตัวเลขอย่างง่ายเช่น 1,2,3,4 นั้นจริง ๆ แล้วคือตัวเลขทั้งหมดในลำดับดังนั้นสำหรับโหมด "โหมด" ที่คล้ายกันนี้จะทำงานตามที่คาดไว้ เช่น modeave (c (1,2,3,4), method = "modes") จะส่งกลับ [1] 1 2 3 4 ไม่ว่าจะด้วยวิธีใดก็ตามฉันสนใจที่จะเห็นฟังก์ชั่นที่ได้รับการปรับให้เหมาะสม สถานะปัจจุบัน
Chris

สำหรับรุ่นที่มีประสิทธิภาพมากขึ้นของฟังก์ชั่นนี้ดู @ hugovdberg โพสต์ดังกล่าวข้างต้น :)
คริส

10

ที่นี่วิธีแก้ปัญหาอื่น:

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

คุณสามารถแทนที่บรรทัดแรกด้วยตาราง
Jonathan Chang

ฉันคิดว่า 'tapply' มีประสิทธิภาพมากกว่า 'table' แต่ทั้งคู่ใช้ a for loop ฉันคิดว่าวิธีแก้ปัญหาที่มีตารางเทียบเท่า ฉันอัพเดตคำตอบ
teucer

9

ฉันยังไม่สามารถลงคะแนนได้ แต่คำตอบของ 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
Sergio

x ควรเป็นเวกเตอร์
AleRuete

8

การปรับเปลี่ยนเล็กน้อยในคำตอบของ Ken Williams เพิ่ม params ที่เป็นตัวเลือก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])
}

หากต้องการแสดงว่าทำงานได้กับ params ที่เป็นตัวเลือกและรักษาประเภทข้อมูล:

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 สำหรับการทำให้เข้าใจง่าย


7

ฉันเขียนโค้ดต่อไปนี้เพื่อสร้างโหมด

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)

6

ใช้ฟังก์ชัน @ Chris เพื่อคำนวณโหมดหรือตัวชี้วัดที่เกี่ยวข้องอย่างไรก็ตามใช้วิธีของ Ken Williams ในการคำนวณความถี่ อันนี้ให้การแก้ไขสำหรับกรณีที่ไม่มีโหมดเลย (องค์ประกอบทั้งหมดบ่อยเท่ากัน) และ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 ฉันเปรียบเทียบมาตรฐานของคำตอบก่อนหน้านี้เพื่อแสดงว่าการทำงานของฉันใกล้เคียงกับประสิทธิภาพการทำงานของเคนอย่างไร เปรียบเทียบฟังก์ชั่นโหมด


รหัสที่คุณนำเสนอดูเหมือนจะเป็นสำเนาตรงของModeฟังก์ชันที่พบในpracmaแพ็คเกจ สนใจที่จะอธิบาย?
AkselA

จริงๆ? เห็นได้ชัดว่าฉันไม่ใช่คนเดียวที่คิดว่านี่เป็นวิธีที่ดีในการคำนวณโหมด แต่ฉันก็ไม่รู้ด้วยซ้ำ ฉันทำความสะอาดฟังก์ชั่นของ Chris และปรับปรุงให้ดีขึ้นโดยใช้เวอร์ชั่นของ Ken และถ้ามันคล้ายกับรหัสของคนอื่นที่บังเอิญโดยสิ้นเชิง
hugovdberg

ฉันมองเข้าไปในตอนนี้ แต่pracmaคุณอ้างถึงแพ็คเกจรุ่นใด เวอร์ชัน 1.9.3 มีการใช้งานที่แตกต่างอย่างสิ้นเชิงเท่าที่ฉันเห็น
hugovdberg

2
การแก้ไขที่ดีกับฟังก์ชั่น หลังจากการอ่านเพิ่มเติมฉันได้นำไปสู่ข้อสรุปว่าไม่มีความเห็นพ้องกันว่าการแจกแจงแบบสม่ำเสมอหรือแบบ monofrequency มีโหนดหรือไม่แหล่งที่มาบอกว่ารายการของโหมดเป็นการกระจายตัวเองส่วนอื่น ๆ ที่ไม่มีโหนด ข้อตกลงเพียงอย่างเดียวคือการผลิตรายการของโหมดสำหรับการแจกแจงดังกล่าวนั้นไม่ได้ให้ข้อมูลหรือมีความหมายมากนัก หากคุณต้องการให้ฟังก์ชันดังกล่าวสร้างโหมดกรณีเช่นนั้นให้ลบบรรทัด: nmodes <- ifelse (nmodes == n, 0L, nmodes)
Chris

1
@greendiod ขออภัยฉันพลาดความคิดเห็นของคุณ มันสามารถใช้ได้ผ่านส่วนสำคัญนี้: gist.github.com/Hugovdberg/0f00444d46efd99ed27bbe227bdc4d37
hugovdberg

6

แฮ็คนี้ควรใช้งานได้ดี ให้คุณค่ารวมถึงจำนวนของโหมด:

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

3

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 (ดี ... โหมด () ตามที่คุณค้นพบว่าถูกใช้เพื่อยืนยันประเภทของตัวแปร )



3

นี่คือฟังก์ชั่นเพื่อค้นหาโหมด:

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

ด้านล่างเป็นรหัสที่สามารถใช้เพื่อค้นหาโหมดของตัวแปรเวกเตอร์ใน R

a <- table([vector])

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

3

มีหลายวิธีแก้ไขสำหรับหนึ่งนี้ ฉันตรวจสอบครั้งแรกและหลังจากนั้นเขียนของฉันเอง โพสต์ไว้ที่นี่ถ้ามันช่วยใครได้:

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

ให้ทดสอบด้วยตัวอย่าง ฉันกำลังใช้irisชุดข้อมูล ให้ทดสอบด้วยข้อมูลตัวเลข

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

ซึ่งคุณสามารถตรวจสอบได้ถูกต้อง

ตอนนี้ฟิลด์ที่ไม่ใช่ตัวเลขเท่านั้นในชุดข้อมูล iris (Species) ไม่มีโหมด ลองทดสอบด้วยตัวอย่างของเราเอง

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

แก้ไข

ตามที่ระบุไว้ในความคิดเห็นผู้ใช้อาจต้องการรักษาประเภทอินพุต ในกรณีนี้ฟังก์ชันโหมดสามารถปรับเปลี่ยนเป็น:

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

บรรทัดสุดท้ายของฟังก์ชั่นจะทำการรวมค่าโหมดสุดท้ายกับประเภทของอินพุตต้นฉบับ


สิ่งนี้จะคืนค่าเป็นปัจจัยในขณะที่ผู้ใช้อาจต้องการรักษาประเภทของอินพุต อาจเพิ่มขั้นตอนกลางy[,1] <- sort(unique(x))
Frank

2

ฉันจะใช้ฟังก์ชั่นความหนาแน่น () เพื่อระบุการกระจายสูงสุดที่ราบรื่น (อาจต่อเนื่อง):

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

โดยที่ x คือการรวบรวมข้อมูล ให้ความสนใจกับการปรับ paremeter ของฟังก์ชั่นความหนาแน่นซึ่งควบคุมการปรับให้เรียบ


2

ในขณะที่ฉันชอบฟังก์ชั่นที่เรียบง่ายของ Ken Williams ฉันต้องการดึงหลาย ๆ โหมดหากมีอยู่ ด้วยความที่อยู่ในใจฉันใช้ฟังก์ชั่นต่อไปนี้ซึ่งจะคืนค่ารายการของโหมดถ้ามีหลายแบบหรือเดี่ยว

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

มันจะสอดคล้องกันมากขึ้นสำหรับการใช้แบบโปรแกรมหากมันส่งคืนรายการ - ความยาว 1 เสมอหากมีเพียงโหมดเดียวเท่านั้น
asac

นั่นเป็นจุดที่ถูกต้อง @ antoine-sac สิ่งที่ฉันชอบเกี่ยวกับวิธีแก้ปัญหานี้คือเวกเตอร์ที่ส่งคืนมา เพียงแสดงที่อยู่เอาท์พุทของฟังก์ชั่น: r <- โหมด (c (2, 2, 3, 3)) ด้วยโหมดที่มีให้ที่ r [1] และ r [2] แต่ถึงกระนั้นคุณทำจุดที่ดี !!
RandallShanePhD

แม่นยำนี่คือที่แก้ปัญหาของคุณสั้น หากmodeส่งคืนรายการที่มีหลายค่าดังนั้น r [1] ไม่ใช่ค่าแรก แทนที่จะเป็นรายการความยาว 1 ที่มีค่าแรกและคุณต้องทำ r [[1]] เพื่อให้ได้โหมดแรกเป็นตัวเลขและไม่ใช่รายการ ตอนนี้เมื่อมีโหมดเดียว r ของคุณไม่อยู่ในรายการดังนั้น r [1] ใช้งานได้ซึ่งเป็นสาเหตุที่ฉันคิดว่ามันไม่สอดคล้องกัน แต่เนื่องจาก r [[1]] ยังใช้งานได้เมื่อ r เป็นเวกเตอร์ง่าย ๆ , มีความสอดคล้องกันจริง ๆ ที่ฉันไม่ได้ตระหนักว่าคุณสามารถใช้งานได้เสมอ[[เพื่อเข้าถึงองค์ประกอบต่างๆ
asac

2

ฉันกำลังดูตัวเลือกทั้งหมดเหล่านี้และเริ่มสงสัยเกี่ยวกับคุณสมบัติและการแสดงของพวกเขาดังนั้นฉันจึงทำการทดสอบบางอย่าง ในกรณีที่คนอื่นอยากรู้เกี่ยวกับเรื่องเดียวกันฉันแบ่งปันผลของฉันที่นี่

ไม่ต้องการยุ่งเกี่ยวกับฟังก์ชั่นทั้งหมดที่โพสต์ที่นี่ฉันเลือกที่จะมุ่งเน้นไปที่ตัวอย่างตามเกณฑ์ไม่กี่: ฟังก์ชั่นควรทำงานทั้งตัวละครปัจจัยตรรกะและเวกเตอร์ตัวเลขมันควรจัดการกับ NAs และค่าที่มีปัญหาอื่น ๆ อย่างเหมาะสม และผลลัพธ์ควรเป็น 'เหมาะสม' เช่นไม่มีตัวเลขเป็นตัวละครหรือความงี่เง่าอื่น ๆ

ฉันยังเพิ่มฟังก์ชั่นของตัวเองซึ่งขึ้นอยู่กับrleแนวคิดเดียวกันกับของ chrispy ยกเว้นดัดแปลงเพื่อการใช้งานทั่วไปมากขึ้น:

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 ฉันคิดว่ามันเป็นสิ่งที่ดี ฉันยังคิดว่ามันน่าสนใจว่าฟังก์ชั่นบางอย่างได้รับผลกระทบจากการเพิ่มค่าที่ไม่ซ้ำใครในขณะที่บางฟังก์ชั่นนั้นไม่มาก ฉันยังไม่ได้ศึกษารายละเอียดของรหัสเพื่อหาสาเหตุที่นอกเหนือจากการกำจัดลอจิคัล / ตัวเลขเป็นสาเหตุ


2

โหมดไม่สามารถมีประโยชน์ในทุกสถานการณ์ ดังนั้นฟังก์ชั่นควรแก้ไขสถานการณ์นี้ ลองใช้ฟังก์ชั่นต่อไปนี้

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

เอาท์พุท

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

ขออภัยฉันไม่เห็นว่าสิ่งนี้จะเพิ่มสิ่งใหม่ในสิ่งที่โพสต์แล้ว นอกจากนี้ผลลัพธ์ของคุณดูเหมือนจะไม่สอดคล้องกับฟังก์ชันของคุณด้านบน
not2qubit

2

สิ่งนี้สร้างขึ้นจากคำตอบของ jprockbelly โดยการเพิ่มความเร็วสำหรับเวกเตอร์ที่สั้นมาก สิ่งนี้มีประโยชน์เมื่อใช้โหมดกับ data.frame หรือ datatable กับกลุ่มเล็ก ๆ จำนวนมาก:

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

ทางออกที่เป็นไปได้อื่น:

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 

1

ฉันกรณีการสังเกตของคุณจะเรียนจากตัวเลขจริงและคุณคาดหวังว่าโหมดจะเป็น 2.5 เมื่อสังเกตของคุณมี 2, 2, 3, และ 3 แล้วคุณสามารถประมาณการโหมดกับmode = l1 + i * (f1-f0) / (2f1 - f0 - f2)ที่l1วงเงิน ..lower ของชั้นที่พบบ่อยที่สุด, f1 .frequency ของคลาสที่บ่อยที่สุด, f0 ..frequency ของคลาสก่อนคลาสที่บ่อยที่สุด, f2 ..frequency ของคลาสหลังจากคลาสที่พบบ่อยที่สุดและi .. ช่วงเวลาคลาสตามที่กำหนดเช่นใน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

ในกรณีที่คุณต้องการระดับที่บ่อยที่สุดและคุณมีระดับที่บ่อยที่สุดมากกว่าหนึ่งระดับคุณสามารถรับระดับทั้งหมดได้เช่น:

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

1

เพิ่มวิธี data.table ที่เป็นไปได้

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

นี่คือหลายวิธีที่คุณสามารถทำได้ในเวลาใช้งาน 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

ลองฟังก์ชั่นต่อไปนี้:

  1. เปลี่ยนค่าตัวเลขให้เป็นปัจจัย
  2. ใช้บทสรุป () เพื่อเพิ่มตารางความถี่
  3. return mode ดัชนีที่มีความถี่มากที่สุด
  4. เปลี่ยนปัจจัยกลับมาเป็นตัวเลขแม้จะมีมากกว่า 1 โหมดฟังก์ชั่นนี้ใช้งานได้ดี!
mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}

0

โหมดการคำนวณเป็นส่วนใหญ่ในกรณีของตัวแปรปัจจัยแล้วเราสามารถใช้

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

HouseVotes84 เป็นชุดข้อมูลที่มีอยู่ในแพ็คเกจ 'mlbench'

มันจะให้มูลค่าฉลากสูงสุด มันง่ายต่อการใช้งานโดยฟังก์ชั่น inbuilt เองโดยไม่ต้องเขียนฟังก์ชั่น


0

สำหรับฉันแล้วดูเหมือนว่าถ้าคอลเลกชันมีโหมดองค์ประกอบของมันสามารถแมปแบบหนึ่งต่อหนึ่งกับตัวเลขธรรมชาติ ดังนั้นปัญหาในการค้นหาโหมดลดการผลิตการทำแผนที่การค้นหาโหมดของค่าที่แมปแล้วแมปกลับไปที่บางรายการในคอลเลกชัน (การจัดการกับNAเกิดขึ้นที่ขั้นตอนการทำแผนที่)

ฉันมีhistogramฟังก์ชั่นที่ทำงานบนหลักการที่คล้ายกัน (ฟังก์ชั่นพิเศษและตัวดำเนินการที่ใช้ในรหัสที่แสดงในที่นี้ควรกำหนดไว้ในชาปิโรส์และ / หรือเดสก์ท็อปเรียบร้อยส่วนของชาปิโรส์และเดสก์ท็อปที่ซ้ำกันในที่นี้ซ้ำกันโดยได้รับอนุญาต ) R pseudocodeสำหรับhistogramคือ

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

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

(ผู้ประกอบการไบนารีพิเศษบรรลุท่อ , ความดีความชอบและองค์ประกอบ ) ฉันยังมีmaxlocฟังก์ชั่นซึ่งคล้ายกับwhich.maxแต่ผลตอบแทนทั้งหมดสูงสุดแน่นอนของเวกเตอร์ R pseudocodeสำหรับ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

แล้วก็

imode <- histogram %O% maxloc

และ

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

จะคำนวณโหมดของการรวบรวมใด ๆ ที่กำหนดฟังก์ชั่นการพิมพ์mapและการพิมพ์ที่เหมาะสมunmap

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.