Hoe vind je de statistische modus?

In R zijn mean()en median()standaardfuncties die doen wat je zou verwachten. mode()vertelt je de interne opslagmodus van het object, niet de waarde die het meest voorkomt in zijn argument. Maar is er een standaard bibliotheekfunctie die de statistische modus voor een vector (of lijst) implementeert?


Antwoord 1, autoriteit 100%

Nog een oplossing, die werkt voor zowel numerieke & karakter-/factorgegevens:

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

Op mijn kleine machine kan dat & vind de modus van een 10M-integer vector in ongeveer een halve seconde.

Als uw dataset mogelijk meerdere modi heeft, gebruikt de bovenstaande oplossing dezelfde benadering als which.max, en retourneert de eerst verschijnendewaarde van de set modi . Gebruik deze variant om allemodi terug te geven (van @digEmAll in de opmerkingen):

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

Antwoord 2, autoriteit 16%

Er is pakket modeestdat schatters biedt van de modus van univariate unimodale (en soms multimodale) gegevens en waarden van de modi van gebruikelijke kansverdelingen.

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

Zie voor meer informatie deze pagina


3, Autoriteit 14%

Vond dit op de R-mailinglijst, hoop dat het nuttig is. Het is ook wat ik sowieso dacht. U wilt tabel () de gegevens, sorteren en vervolgens de voornaam kiezen. Het is hackish, maar zou moeten werken.

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

4, Autoriteit 12%

Ik vond Ken Williams Post hierboven om geweldig te zijn, ik heb een paar regels toegevoegd om rekening te houden met NA-waarden en maakte het voor gemak een functie.

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, Autoriteit 9%

Een snelle en vuile manier van het schatten van de modus van een vector van nummers die u gelooft van een continue univariate distributie (bijvoorbeeld een normale distributie) definieert en het gebruik van de volgende functie:

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

Verkrijg vervolgens om de modusschatting te krijgen:

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, Autoriteit 3%

De volgende functie is in drie formulieren:

Methode = “Modus” [Standaard]: Berekent de modus voor een unimodale vector, anders retourneert een Na-
Methode = “NModes”: berekent het aantal modi in de vector
Methode = “Modi”: geeft alle modi op voor een unimodale of polymodale vector

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

Antwoord 7, autoriteit 2%

Hier, nog een oplossing:

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

Antwoord 8, autoriteit 2%

Ik kan nog niet stemmen, maar het antwoord van Rasmus Bååth is wat ik zocht.
Ik zou het echter een beetje aanpassen om de distributie te beperken, bijvoorbeeld voor waarden tussen 0 en 1.

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

We zijn ons ervan bewust dat u misschien niet op al uw distributie wilt beperken, vervolgens instellen van = – “Big Number”, naar = “Big Number”


9, Autoriteit 2%

Ik heb de volgende code geschreven om de modus te genereren.

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

Laten we het proberen:

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

10, Autoriteit 2%

Gebaseerd op de functie van @ Chris om de modus of aanverwante statistieken te berekenen, maar het gebruik van de methode van Ken Williams om frequenties te berekenen. Deze levert een oplossing voor het geval van geen modi überhaupt (alle elementen die even frequent zijn) en wat meer leesbare methodnamen.

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

Omdat het Ken’s methode gebruikt om frequenties te berekenen, zijn de prestaties ook geoptimaliseerd. Met behulp van AkselA’s post heb ik een aantal van de eerdere antwoorden gebenchmarkt om te laten zien hoe mijn functie qua prestaties dicht bij die van Ken ligt, met de voorwaarden voor de verschillende uitvoeropties die alleen kleine overhead:


Antwoord 11

Deze hack zou goed moeten werken. Geeft u zowel de waarde als de telling van de modus:

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

Antwoord 12

R heeft zoveel add-on-pakketten dat sommige ervan de [statistische] modus van een numerieke lijst/reeks/vector kunnen bieden.

De standaardbibliotheek van R zelf lijkt echter niet zo’n ingebouwde methode te hebben! Een manier om dit te omzeilen is om een constructie te gebruiken zoals de volgende (en om dit om te zetten in een functie als je het vaak gebruikt…):

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

Voor een grotere steekproeflijst zou men moeten overwegen een tijdelijke variabele te gebruiken voor de max(tabSmpl) waarde (ik weet niet of R dit automatisch zou optimaliseren)

Referentie: zie “Hoe zit het met mediaan en modus?” in deze KickStarting R-les
Dit lijkt te bevestigen dat (tenminste vanaf het moment van schrijven van deze les) er geen modusfunctie is in R (nou ja… modus() zoals je hebt ontdekt, wordt gebruikt om het type variabelen te bevestigen).


Antwoord 13

Dit werkt redelijk goed

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

Antwoord 14

Hier is een functie om de modus te vinden:

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

Antwoord 15

Hieronder staat de code die kan worden gebruikt om de modus van een vectorvariabele in R te vinden.

a <- table([vector])
names(a[a==max(a)])

Antwoord 16

Hier zijn meerdere oplossingen voor. Ik controleerde de eerste en schreef daarna mijn eigen. Post het hier als het iemand helpt:

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

Laten we het met een paar voorbeeld testen. Ik neem de irisdataset. Laten we testen met numerieke gegevens

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

die u kunt verifiëren is correct.

Nu het enige numerieke veld in de IRIS-dataset (soorten) heeft geen modus. Laten we testen met ons eigen voorbeeld

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

Bewerken

Zoals vermeld in de opmerkingen, wil de gebruiker misschien het invoertype behouden. In welk geval de functie-functie kan worden gewijzigd met:

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

De laatste regel van de functie dwingt simpelweg de definitieve moduswaarde aan het type van de originele ingang.


17

Nog een eenvoudige optie die alle waarden op basis van frequentie geeft, is het gebruik van rle:

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

18

Terwijl ik van Ken Williams Eenvoudige functie leuk wil, wil ik de meerdere modi ophalen als ze bestaan. Met dat in gedachten gebruik ik de volgende functie die een lijst met de modi retourneert als meerdere of de single.

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

19

Ik keek door al deze opties en begon zich af te vragen over hun relatieve kenmerken en uitvoeringen, dus ik heb wat tests gedaan. In het geval dat iemand anders ongeveer hetzelfde is, deel ik mijn resultaten hier.

Nog niet de moeite te nemen over alle functies die hier hebben gepost, heb ik ervoor gekozen om te focussen op een monster op basis van een paar criteria: de functie zou moeten werken aan zowel karakter, factor, logische en numerieke vectoren, het moet omgaan met NAS en andere problematisch Waarden op de juiste manier en de uitvoer moet ‘verstandig’ zijn, dat wil zeggen geen numeriek als karakter of andere dergelijke dwaasheid.

Ik heb ook een eigen functie toegevoegd, die is gebaseerd op dezelfde rleidee als chrispy’s, behalve aangepast voor meer algemene gebruik:

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

Ik heb uiteindelijk vijf functies uitgevoerd, op twee sets testgegevens, via microbenchmark. De functienamen verwijzen naar hun respectievelijke auteurs:

Chris’ functie was standaard ingesteld op method="modes"en na.rm=TRUEom het beter vergelijkbaar te maken, maar verder werden de functies gebruikt zoals hier gepresenteerd door hun auteurs.

Alleen al op het gebied van snelheid wint Kens-versie handig, maar het is ook de enige van deze die slechts één modus rapporteert, ongeacht hoeveel er in werkelijkheid zijn. Zoals vaak het geval is, is er een afweging tussen snelheid en veelzijdigheid. In method="mode"zal de versie van Chris een waarde retourneren als er één modus is, anders NA. Ik vind dat een mooi gebaar.
Ik vind het ook interessant hoe sommige functies worden beïnvloed door een groter aantal unieke waarden, terwijl andere dat lang niet zo veel zijn. Ik heb de code niet in detail bestudeerd om erachter te komen waarom dat is, behalve het elimineren van logisch/numeriek als oorzaak.


Antwoord 20

Modus kan niet in elke situatie handig zijn. Dus de functie zou deze situatie moeten aanpakken. Probeer de volgende functie.

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

Uitvoer,

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

Antwoord 21

Dit bouwt voort op het antwoord van jprockbelly, door een versnelling toe te voegen voor zeer korte vectoren. Dit is handig wanneer de modus wordt toegepast op een data.frame of datatabel met veel kleine groepen:

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

Antwoord 22

De generieke functie fmodein het pakket collapsedat nu beschikbaar is op CRAN, implementeert een op C++ gebaseerde modus op basis van index-hashing. Het is aanzienlijk sneller dan een van de bovenstaande benaderingen. Het wordt geleverd met methoden voor vectoren, matrices, data.frames en dplyr-gegroepeerde tibbles. Syntaxis:

fmode(x, g = NULL, w = NULL, ...)

waar xeen van de bovenstaande objecten kan zijn, glevert een optionele groepsvector of lijst met groepsvectoren (voor de berekeningen van de gegroepeerde modus, ook uitgevoerd in C++), en w(optioneel) levert een numerieke gewichtsvector. In de gegroepeerde TIBLIBLE-methode is er geen gargument, u kunt doen data %>% group_by(idvar) %>% fmode.


23

Nog een mogelijke oplossing:

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

Gebruik:

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

Uitgang:

  user  system elapsed 
   0.32    0.00    0.31 

24

I Case Uw observaties zijn klassen van echte cijfers en U verwacht dat de -modus 2,5 is wanneer uw opmerkingen 2, 2, 3 en 3 zijn, dan zou u de modus kunnen schatten met mode = l1 + i * (f1-f0) / (2f1 - f0 - f2)waarbij L1 .. Lagere limiet van meest frequente klasse, F1 .. Frequentie van meest frequente klasse, F0 .. Frequentie van de lessen vóór de meeste frequente klasse, F2 .. Frequentie van klassen na de meeste frequente klasse en I .. Klasse-interval zoals vermeld in 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

Als u wilt dat u de Meest frequente niveau en u hebt meer dan één het meest voorkomende niveau waarvan u ze allemaal kunt krijgen, bijvoorbeeld met:

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

25

kan de volgende functie proberen:

  1. transformeer numerieke waarden in factor
  2. Gebruik Samenvatting () om de frequentietabel te verkrijgen
  3. retourmodus De index waarvan de frequentie de grootste is
  4. Transform factor Terug naar numeriek Zelfs zijn er meer dan 1 modus, deze functie werkt goed!
mode <- function(x){
  y <- as.factor(x)
  freq <- summary(y)
  mode <- names(freq)[freq[names(freq)] == max(freq)]
  as.numeric(mode)
}

26

De rekenmodus is meestal in het geval van factorvariabele, dan kunnen we

gebruiken

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

Houseevotes84 is dataset beschikbaar in het pakket ‘Mlbench’.

het geeft maximale labelwaarde. Het is gemakkelijker te gebruiken door ingebouwde functies zelf zonder schrijffunctie.


27

Het lijkt mij dat als een verzameling een modus heeft, dan kunnen zijn elementen één-op-één worden toegewezen met de natuurlijke nummers. Het probleem van het vinden van de modus vermindert dus tot het produceren van een dergelijke mapping, het vinden van de modus van de toegewezen waarden, en vervolgens terug te kaarten naar enkele van de items in de collectie. (Omgaan met NAvindt plaats bij de MAPPINGFASE).

Ik heb een histogram-functie die op een vergelijkbare principal werkt. (De speciale functies en operatoren die in de hier gepresenteerde code worden gebruikt, moeten worden gedefinieerd in Shapiroen/of de neatOveRse. De delen van Shapiro en properOveRse die hierin worden gedupliceerd, zijn zo gedupliceerd met toestemming; de gedupliceerde fragmenten mogen worden gebruikt onder de voorwaarden van deze site.) R pseudocodevoor histogramis

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

(De speciale binaire operatoren zorgen voor piping, curryingen compositie) Ik heb ook een functie maxloc, die vergelijkbaar is met which.max, maar allde absolute maxima van een vector. R pseudocodevoor 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

Dan

imode <- histogram %O% maxloc

en

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

berekent de modus van elke verzameling, op voorwaarde dat de juiste functies map-ping en unmap-ping zijn gedefinieerd.


Antwoord 28

Toevoegen in raster::modal()als een optie, maar houd er rekening mee dat rastereen fors pakket is en misschien niet de moeite waard is om te installeren als u geen geospatial doet werk.

De broncode kan uit https://github worden gehaald .com/rspatial/raster/blob/master/src/modal.cppen https://github.com/rspatial/raster/blob/master/R/modal.Rin een persoonlijk R-pakket, voor degenen die bijzonder geïnteresseerd zijn.

Other episodes