Apakah ada fungsi bawaan untuk menemukan mode?

392

Di R, mean()dan median()merupakan fungsi standar yang melakukan apa yang Anda harapkan. mode()memberi tahu Anda mode penyimpanan internal objek, bukan nilai yang paling banyak muncul dalam argumennya. Tetapi apakah ada fungsi perpustakaan standar yang mengimplementasikan mode statistik untuk vektor (atau daftar)?

Nick
sumber
4
Anda perlu mengklarifikasi apakah data Anda bilangan bulat, numerik, faktor ...? Estimasi mode untuk angka akan berbeda, dan menggunakan interval. Lihat modeest
smci
2
Mengapa R tidak memiliki fungsi bawaan untuk mode? Mengapa R dianggap modesama dengan fungsinya class?
Corey Levinson

Jawaban:

400

Satu lagi solusi, yang berfungsi untuk data numerik & karakter / faktor:

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

Pada mesin mungil mungil saya, yang dapat menghasilkan & menemukan mode vektor 10M-integer dalam waktu sekitar setengah detik.

Jika kumpulan data Anda memiliki beberapa mode, solusi di atas mengambil pendekatan yang sama dengan which.max, dan mengembalikan nilai yang muncul pertama dari set mode. Untuk mengembalikan semua mode, gunakan varian ini (dari @digEmAll di komentar):

Modes <- function(x) {
  ux <- unique(x)
  tab <- tabulate(match(x, ux))
  ux[tab == max(tab)]
}
Ken Williams
sumber
7
Juga berfungsi untuk logika! Mempertahankan tipe data untuk semua jenis vektor (tidak seperti beberapa implementasi dalam jawaban lain).
DavidC
39
Ini tidak mengembalikan semua mode dalam kasus dataset multi-modal (misalnya c(1,1,2,2)). Anda harus mengubah baris terakhir Anda dengan:tab <- tabulate(match(x, ux)); ux[tab == max(tab)]
digEmAll
6
@verybadatthis Untuk itu, Anda akan menggantinya ux[which.max(tabulate(match(x, ux)))]dengan adil max(tabulate(match(x, ux))).
Ken Williams
4
Anda perhatikan bahwa Mode(1:3)memberi 1dan Mode(3:1)memberi 3, sehingga Mode mengembalikan elemen paling sering atau yang pertama jika semuanya unik.
Enrique Pérez Herrero
2
Seperti yang dikatakan Enrique: Ini gagal ketika tidak ada mode, dan sebaliknya memberi Anda kesan bahwa nilai pertama adalah mode. Akan jauh lebih baik jika dikembalikan 0atau NAdalam kasus itu.
not2qubit
66

Ada paket modeestyang menyediakan penduga mode univariat data unimodal (dan kadang-kadang multimodal) dan nilai mode distribusi probabilitas biasa.

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

Untuk informasi lebih lanjut lihat halaman ini

George Dontas
sumber
7
Jadi hanya untuk mendapatkan nilai mode mfv(mySamples)[1],. The 1menjadi penting karena sebenarnya mengembalikan nilai yang paling sering s .
atomic
sepertinya tidak berfungsi dalam contoh ini: library (modeest) a <- rnorm (50, 30, 2) b <- rnorm (100, 35, 2) c <- rnorm (20, 37, 2) temperatureºC <- c (a, b, c) hist (suhu ºC) #adalah abline (v = rata-rata (suhu ºC), col = "red", lwd = 2) #median abline (v = median (suhu ºC), col = "hitam", lwd = 2) #mode abline (v = mlv (suhuºC, metode = "mfv") [1], col = "orange", lwd = 2)
Agus camacho
1
@atomicules: dengan [1] Anda hanya mendapatkan mode pertama. Untuk distribusi bimodal atau n-modal umum, Anda hanya perlumfv(mySamples)
petzi
1
Untuk R versi 3.6.0, dikatakan fungsi 'tidak dapat menemukan fungsi "mlv"' dan kesalahan yang sama ketika saya mencoba mfv (mysamples). Apakah didepresiasi?
Dr Nisha Arora
@DrNishaArora: Apakah Anda mengunduh paket 'modeest'?
petzi
59

menemukan ini di r mailing list, semoga bermanfaat. Itu juga yang saya pikirkan. Anda ingin membuat tabel () data, mengurutkan dan kemudian memilih nama depan. Ini retas tetapi harus bekerja.

names(sort(-table(x)))[1]
Dan
sumber
6
Itu juga pekerjaan yang cerdas. Ini memiliki beberapa kelemahan: algoritma pengurutan dapat lebih memakan tempat dan waktu daripada pendekatan berbasis max () (=> harus dihindari untuk daftar sampel yang lebih besar). Juga ouput adalah mode (maafkan kata-kata / ambiguitas) "karakter" bukan "numerik". Dan, tentu saja, kebutuhan untuk menguji distribusi multi-modal biasanya akan memerlukan penyimpanan tabel yang diurutkan untuk menghindari pengerasan baru.
mjv
2
Saya mengukur waktu berjalan dengan faktor elemen 1e6 dan solusi ini lebih cepat daripada jawaban yang diterima oleh hampir faktor 3!
vonjd
Saya baru saja mengubahnya menjadi angka menggunakan as.numeric (). Bekerja dengan sangat baik. Terima kasih!
Abhishek Singh
47

Saya menemukan posting Ken Williams di atas sangat bagus, saya menambahkan beberapa baris untuk menjelaskan nilai-nilai NA dan membuatnya berfungsi untuk memudahkan.

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)))])
}
jprockbelly
sumber
Saya telah menemukan beberapa percepatan untuk ini, lihat jawaban di bawah.
Dan Houghton
33

Cara cepat dan kotor dalam memperkirakan mode vektor angka yang Anda yakini berasal dari distribusi univariat berkelanjutan (mis. Distribusi normal) adalah mendefinisikan dan menggunakan fungsi berikut:

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

Kemudian untuk mendapatkan estimasi mode:

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
Rasmus Bååth
sumber
3
Hanya sebuah catatan untuk yang ini: Anda bisa mendapatkan "mode" dari grup nomor mana pun dengan cara ini. Data tidak perlu berasal dari distribusi normal untuk bekerja. Berikut adalah contoh pengambilan angka dari distribusi yang seragam. 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 Pesan kesalahan itu memberi tahu Anda semua yang perlu Anda ketahui. Jika Anda hanya memiliki satu titik, Anda perlu mengatur bandwidth secara manual saat menelepon density. Namun, jika Anda hanya memiliki satu datapoint maka nilai dari datapoint itu mungkin akan menjadi tebakan terbaik Anda untuk mode ini ...
Rasmus Bååth
Anda benar, tetapi saya menambahkan hanya satu tweak: estimate_mode <- function(x) { if (length(x)>1){ d <- density(x) d$x[which.max(d$y)] }else{ x } } Saya sedang menguji metode untuk memperkirakan arah angin dominan, daripada rata-rata arah menggunakan rata-rata vektorial dengan paket melingkar. Saya bekerja dengan poin di atas nilai poligon, jadi, kadang-kadang hanya ada satu titik dengan arah. Terima kasih!
Sergio
@xhie Kedengarannya masuk akal :)
Rasmus Bååth
14

Fungsi berikut hadir dalam tiga bentuk:

method = "mode" [default]: menghitung mode untuk vektor unimodal, kalau tidak mengembalikan
metode NA = "nmodes": menghitung jumlah mode dalam
metode vektor = "mode": daftar semua mode untuk unimodal atau polymodal vektor

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()
}
Chris
sumber
Dalam deskripsi Anda tentang fungsi ini, Anda menukar "mode" dan "nmodes". Lihat kodenya. Sebenarnya, "nmodes" mengembalikan vektor nilai dan "mode" mengembalikan jumlah mode. Bagaimanapun fungsi Anda adalah soultion terbaik untuk menemukan mode yang saya lihat sejauh ini.
Grzegorz Adam Kowalski
Terima kasih banyak atas komentarnya. "nmode" dan "mode" sekarang harus berperilaku seperti yang diharapkan.
Chris
Fungsi Anda hampir berfungsi, kecuali ketika setiap nilai muncul sama seringnya menggunakan method = 'modes'. Kemudian fungsi mengembalikan semua nilai unik, namun sebenarnya tidak ada mode sehingga harus dikembalikan NAsebagai gantinya. Saya akan menambahkan jawaban lain yang berisi versi fungsi Anda yang sedikit dioptimalkan, terima kasih atas inspirasi!
hugovdberg
Satu-satunya waktu vektor numerik non-kosong biasanya menghasilkan NA dengan fungsi ini adalah ketika menggunakan metode default pada vektor polymodal. Mode urutan angka sederhana seperti 1,2,3,4 sebenarnya semua angka tersebut dalam urutan, jadi untuk urutan yang sama "mode" berperilaku seperti yang diharapkan. misalnya modeave (c (1,2,3,4), method = "mode") mengembalikan [1] 1 2 3 4 Terlepas dari ini, saya akan sangat tertarik untuk melihat fungsi dioptimalkan karena cukup intensif sumber daya dalam kondisi saat ini
Chris
Untuk versi yang lebih efisien dari fungsi ini, lihat posting @ hugovdberg di atas :)
Chris
10

Di sini, solusi lain:

freq <- tapply(mySamples,mySamples,length)
#or freq <- table(mySamples)
as.numeric(names(freq)[which.max(freq)])
penggoda
sumber
Anda dapat mengganti baris pertama dengan tabel.
Jonathan Chang
Saya berpikir bahwa 'tapply' lebih efisien daripada 'table', tetapi mereka berdua menggunakan for for loop. Saya pikir solusi dengan tabel setara. Saya memperbarui jawabannya.
Penggoda
9

Saya belum bisa memilih tetapi jawaban Rasmus Bååth adalah yang saya cari. Namun, saya akan memodifikasinya sedikit memungkinkan untuk membatasi distribusi misalnya hanya nilai antara 0 dan 1.

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

Kami menyadari bahwa Anda mungkin tidak ingin membatasi sama sekali pada distribusi Anda, lalu mengatur dari = - "NOMOR BESAR", hingga = "NOMOR BESAR"

AleRuete
sumber
error in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
Sergio
x harus berupa vektor
AleRuete
8

Modifikasi kecil untuk jawaban Ken Williams, menambahkan params opsional na.rmdan return_multiple.

Berbeda dengan jawaban yang mengandalkan names(), jawaban ini mempertahankan tipe data xdalam nilai yang dikembalikan.

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

Untuk menunjukkannya berfungsi dengan params opsional dan memelihara tipe data:

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"

Berkat @ Frank untuk penyederhanaan.

C8H10N4O2
sumber
7

Saya telah menulis kode berikut untuk menghasilkan mode.

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

Mari kita coba:

MODE(mtcars)
MODE(CO2)
MODE(ToothGrowth)
MODE(InsectSprays)
Tyler Rinker
sumber
6

Berdasarkan fungsi @ Chris untuk menghitung mode atau metrik terkait, namun menggunakan metode Ken Williams untuk menghitung frekuensi. Yang satu ini menyediakan perbaikan untuk kasus tidak ada mode sama sekali (semua elemen sama-sama sering), dan beberapa methodnama yang lebih mudah dibaca .

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

Karena menggunakan metode Ken untuk menghitung frekuensi, kinerjanya juga dioptimalkan, menggunakan postingan AkselA, saya membandingkan beberapa jawaban sebelumnya untuk menunjukkan bagaimana fungsi saya dekat dengan kinerja Ken, dengan persyaratan untuk berbagai opsi ouput yang hanya menyebabkan sedikit overhead: Perbandingan fungsi Mode

hugovdberg
sumber
Kode yang Anda berikan tampaknya merupakan salinan Modefungsi yang ditemukan dalam pracmapaket. Mau jelaskan?
AkselA
Betulkah? Rupanya saya bukan satu-satunya yang berpikir ini adalah cara yang baik untuk menghitung Mode, tapi saya jujur ​​tidak tahu itu (tidak pernah tahu paket itu sebelumnya). Saya membersihkan fungsi Chris dan memperbaikinya dengan memanfaatkan versi Ken, dan jika itu menyerupai kode orang lain yang murni kebetulan.
hugovdberg
Saya melihat ke dalamnya sekarang, tetapi versi pracmapaket yang Anda rujuk? Versi 1.9.3 memiliki implementasi yang sama sekali berbeda sejauh yang saya bisa lihat.
hugovdberg
2
Amandemen fungsi yang bagus. Setelah beberapa bacaan lebih lanjut, saya mengarah pada kesimpulan bahwa tidak ada konsensus tentang apakah distribusi seragam atau monofrekuensi memiliki node, beberapa sumber mengatakan bahwa daftar mode adalah distribusi sendiri, yang lain bahwa tidak ada simpul. Satu-satunya kesepakatan adalah bahwa memproduksi daftar mode untuk distribusi semacam itu tidak terlalu informatif atau sangat bermakna. JIKA Anda ingin fungsi di atas untuk menghasilkan mode kasus seperti itu kemudian hapus baris: nmodes <- ifelse (nmodes == n, 0L, nmodes)
Chris
1
@ Grendiod maaf, saya ketinggalan komentar Anda. Ini tersedia melalui intisari ini: gist.github.com/Hugovdberg/0f00444d46efd99ed27bbe227bdc4d37
hugovdberg
6

Peretasan ini seharusnya bekerja dengan baik. Memberi Anda nilai serta hitungan mode:

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

R memiliki begitu banyak paket tambahan yang beberapa di antaranya mungkin menyediakan mode [statistik] dari daftar numerik / seri / vektor.

Namun pustaka standar R itu sendiri tampaknya tidak memiliki metode bawaan! Salah satu cara untuk mengatasi ini adalah dengan menggunakan beberapa konstruksi seperti berikut (dan untuk mengubahnya menjadi fungsi jika Anda sering menggunakan ...):

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

Untuk daftar sampel yang lebih besar, orang harus mempertimbangkan menggunakan variabel sementara untuk nilai maks (tabSmpl) (saya tidak tahu bahwa R akan secara otomatis mengoptimalkan ini)

Referensi: lihat "Bagaimana dengan median dan mode?" dalam pelajaran KickStarting R
ini Tampaknya mengkonfirmasi bahwa (setidaknya pada saat penulisan pelajaran ini) tidak ada fungsi mode dalam R (well ... mode () seperti yang Anda temukan digunakan untuk menyatakan jenis variabel ).

mjv
sumber
3

Ini bekerja dengan sangat baik

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

Berikut adalah fungsi untuk menemukan mode:

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)
}
Ernest S Kirubakaran
sumber
3

Di bawah ini adalah kode yang dapat digunakan untuk menemukan mode variabel vektor dalam R.

a <- table([vector])

names(a[a==max(a)])
GauravS
sumber
3

Ada beberapa solusi yang disediakan untuk yang satu ini. Saya memeriksa yang pertama dan setelah itu menulis sendiri. Posting di sini jika itu membantu siapa pun:

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

Mari kita mengujinya dengan beberapa contoh. Saya mengambil iriskumpulan data. Mari kita uji dengan data numerik

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

yang dapat Anda verifikasi benar.

Sekarang satu-satunya bidang non numerik dalam set data iris (Spesies) tidak memiliki mode. Mari kita coba dengan contoh kita sendiri

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

EDIT

Seperti disebutkan dalam komentar, pengguna mungkin ingin mempertahankan tipe input. Dalam hal ini fungsi mode dapat dimodifikasi untuk:

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

Baris terakhir fungsi hanya memaksa nilai mode akhir ke jenis input asli.

Abhiroop Sarkar
sumber
Ini mengembalikan suatu faktor, sementara pengguna mungkin ingin mempertahankan jenis input. Mungkin tambahkan langkah tengahy[,1] <- sort(unique(x))
Frank
2

Saya akan menggunakan fungsi density () untuk mengidentifikasi distribusi maksimum (mungkin berkesinambungan) yang dihaluskan:

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

di mana x adalah pengumpulan data. Perhatikan paremeter yang menyesuaikan fungsi kepadatan yang mengatur smoothing.

Yo B.
sumber
2

Sementara saya menyukai fungsi sederhana Ken Williams, saya ingin mengambil beberapa mode jika ada. Dengan mengingat hal itu, saya menggunakan fungsi berikut yang mengembalikan daftar mode jika banyak atau tunggal.

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)) )]
} 
RandallShanePhD
sumber
Akan lebih konsisten untuk penggunaan program jika selalu mengembalikan daftar - panjang 1 jika hanya ada satu mode
asac
Itu poin yang valid @ antoine-sac. Apa yang saya sukai dari solusi ini adalah vektor yang dikembalikan meninggalkan jawaban yang mudah dialamatkan. Cukup alamat keluaran fungsi: r <- mode (c (2, 2, 3, 3)) dengan mode yang tersedia di r [1] dan r [2]. Tetap saja, Anda membuat poin yang bagus !!
RandallShanePhD
Tepatnya, di sinilah solusi Anda gagal. Jika modemengembalikan daftar dengan beberapa nilai, maka r [1] bukan nilai pertama; itu bukan daftar panjang 1 yang berisi nilai pertama dan Anda harus melakukan r [[1]] untuk mendapatkan mode pertama sebagai numerik dan bukan daftar. Sekarang ketika ada satu mode, r Anda bukan daftar jadi r [1] berfungsi, itulah sebabnya saya pikir itu tidak konsisten. Tetapi karena r [[1]] juga berfungsi ketika r adalah vektor sederhana, sebenarnya ada konsistensi yang tidak saya sadari bahwa Anda selalu dapat menggunakan [[untuk mengakses elemen.
asac
2

Saya melihat-lihat semua opsi ini dan mulai bertanya-tanya tentang fitur dan penampilan relatif mereka, jadi saya melakukan beberapa tes. Jika ada orang yang ingin tahu tentang hal yang sama, saya membagikan hasil saya di sini.

Tidak ingin repot dengan semua fungsi yang diposting di sini, saya memilih untuk fokus pada sampel berdasarkan beberapa kriteria: fungsi tersebut harus bekerja pada kedua karakter, vektor faktor, logis dan numerik, harus berurusan dengan NAS dan nilai bermasalah lainnya dengan tepat, dan output harus 'masuk akal', yaitu tidak ada angka sebagai karakter atau kekonyolan lainnya.

Saya juga menambahkan fungsi saya sendiri, yang didasarkan pada rleide yang sama dengan chrispy, kecuali diadaptasi untuk penggunaan yang lebih umum:

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

Saya akhirnya menjalankan lima fungsi, pada dua set data uji, sampai microbenchmark. Nama fungsi merujuk ke penulis masing-masing:

masukkan deskripsi gambar di sini

Fungsi Chris diatur ke method="modes"danna.rm=TRUE secara default untuk membuatnya lebih sebanding, tetapi selain itu fungsi digunakan seperti yang disajikan di sini oleh penulisnya.

Dalam hal kecepatan saja, versi Kens menang dengan mudah, tetapi ini juga satu-satunya yang hanya akan melaporkan satu mode, tidak peduli berapa banyak sebenarnya. Seperti yang sering terjadi, ada pertukaran antara kecepatan dan keserbagunaan. Dalam method="mode", versi Chris akan mengembalikan nilai jika ada satu mode, selain itu NA. Saya pikir itu sentuhan yang bagus. Saya juga berpikir itu menarik bagaimana beberapa fungsi dipengaruhi oleh peningkatan jumlah nilai unik, sementara yang lain tidak sebanyak. Saya belum mempelajari kode secara rinci untuk mencari tahu mengapa itu, selain menghilangkan logis / numerik sebagai penyebabnya.

AkselA
sumber
2

Mode tidak dapat berguna dalam setiap situasi. Jadi fungsinya harus mengatasi situasi ini. Coba fungsi berikut.

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

Keluaran,

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."
Jibin
sumber
Maaf, saya hanya tidak melihat bagaimana ini menambahkan sesuatu yang baru ke apa yang sudah diposting. Selain itu, output Anda tampaknya tidak konsisten dengan fungsi Anda di atas.
not2qubit
2

Ini dibangun berdasarkan jawaban jprockbelly, dengan menambahkan kecepatan untuk vektor yang sangat singkat. Ini berguna ketika menerapkan mode ke data.frame atau datatable dengan banyak grup kecil:

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)))]
}
Dan Houghton
sumber
1

Opsi sederhana lain yang memberikan semua nilai yang dipesan berdasarkan frekuensi adalah menggunakan rle:

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

Solusi lain yang mungkin:

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

Pemakaian:

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

Keluaran:

   user  system elapsed 
   0.32    0.00    0.31 
Naimish Agarwal
sumber
1

Saya perhatikan pengamatan Anda adalah kelas dari bilangan real dan Anda berharap bahwa mode menjadi 2,5 ketika pengamatan Anda adalah 2, 2, 3, dan 3 maka Anda dapat memperkirakan mode dengan di mode = l1 + i * (f1-f0) / (2f1 - f0 - f2)mana l1 .. batas lebih rendah dari kelas paling sering, f1 . Frekuensi kelas paling sering, f0 .. frekuensi kelas sebelum kelas paling sering, f2 .. frekuensi kelas setelah kelas paling sering dan saya .. Interval kelas seperti yang diberikan misalnya dalam 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

Jika Anda menginginkan level yang paling sering dan Anda memiliki lebih dari satu level yang paling sering, Anda bisa mendapatkan semuanya misalnya dengan:

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

Menambahkan kemungkinan pendekatan 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)}]
chinsoon12
sumber
1

Berikut adalah beberapa cara yang dapat Anda lakukan dalam menjalankan waktu 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))
Paul Sartre
sumber
0

Bisa mencoba fungsi berikut:

  1. mengubah nilai numerik menjadi faktor
  2. gunakan ringkasan () untuk mendapatkan tabel frekuensi
  3. mode pengembalian indeks yang frekuensinya terbesar
  4. mengubah faktor kembali ke numerik walaupun ada lebih dari 1 mode, fungsi ini berfungsi dengan baik!
mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}
Wei
sumber
0

Mode Menghitung sebagian besar dalam hal variabel faktor maka kita dapat menggunakan

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

HouseVotes84 adalah dataset yang tersedia dalam paket 'mlbench'.

itu akan memberikan nilai label max. lebih mudah digunakan dengan fungsi inbuilt itu sendiri tanpa fungsi penulisan.

Ashutosh Agrahari
sumber
0

Menurut saya, jika koleksi memiliki mode, maka elemen-elemennya dapat dipetakan satu-ke-satu dengan bilangan asli. Jadi, masalah menemukan mode berkurang menjadi menghasilkan pemetaan seperti itu, menemukan mode nilai yang dipetakan, lalu memetakan kembali ke beberapa item dalam koleksi. (Berurusan dengan NAterjadi pada fase pemetaan).

Saya memiliki histogramfungsi yang beroperasi pada prinsipal yang serupa. (Fungsi dan operator khusus yang digunakan dalam kode yang disajikan di sini harus didefinisikan dalam Shapiro dan / atau neatOveRse . Bagian-bagian dari Shapiro dan neatOveRse yang diduplikasi di sini sangat digandakan dengan izin; snipet yang digandakan dapat digunakan berdasarkan ketentuan situs ini. ) R pseudocode untuk histogramis

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

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

(Operator biner khusus menyelesaikan perpipaan , currying , dan komposisi ) Saya juga punyamaxloc fungsi, yang mirip dengan which.max, tetapi mengembalikan semua maxima absolut vektor. R pseudocode untuk maxlocis

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

Kemudian

imode <- histogram %O% maxloc

dan

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

akan menghitung mode koleksi apa pun, asalkan sesuai mapdanunmap fungsi- -ping yang sesuai didefinisikan.

Ana Nimbus
sumber