R中,mean()
和 median()
是标准函数,它们执行你期望的操作。 mode()
返回对象内部存储模式,而不是其参数中出现最多的值。但是否有一个标准库函数可以实现向量(或列表)的统计众数?
R中,mean()
和 median()
是标准函数,它们执行你期望的操作。 mode()
返回对象内部存储模式,而不是其参数中出现最多的值。但是否有一个标准库函数可以实现向量(或列表)的统计众数?
还有一种解决方法,适用于数值和字符/因子数据:
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
在我的小型计算机上,可以在约半秒钟内生成并找到一个包含1000万个整数的向量的众数。
如果您的数据集可能有多个众数,则上述解决方案采用与which.max
相同的方法,并返回众数集合中出现的第一个值。 要返回所有众数,请使用此变体(来自评论中的@digEmAll):
Modes <- function(x) {
ux <- unique(x)
tab <- tabulate(match(x, ux))
ux[tab == max(tab)]
}
c(1,1,2,2)
),这并不返回所有模式。你应该将最后一行改为:tab <- tabulate(match(x, ux)); ux[tab == max(tab)]
。 - digEmAllux[which.max(tabulate(match(x, ux)))]
替换为max(tabulate(match(x, ux)))
。 - Ken WilliamsMode(1:3)
返回 1
,而 Mode(3:1)
返回 3
,因此 Mode 函数返回最常见的元素,如果所有元素都是唯一的,则返回第一个元素。 - Enrique Pérez Herrero0
或NA
将会更好。 - not2qubit在 R 邮件列表中找到这个,希望它有所帮助。这也是我一直在想的。您需要对数据进行 table(),排序然后选择第一个名称。这很 hackish 但应该能用。
names(sort(-table(x)))[1]
有一个叫做modeest
的包,它提供了单一峰值(有时也是多峰值)数据的估计模式以及通常概率分布的模式值。
mySamples <- c(19, 4, 5, 7, 29, 19, 29, 13, 25, 19)
library(modeest)
mlv(mySamples, method = "mfv")
Mode (most likely value): 19
Bickel's modal skewness: -0.1
Call: mlv.default(x = mySamples, method = "mfv")
更多信息请参见此页面
您还可以在CRAN任务视图:概率分布中寻找“模式估计”。已提出两个新软件包。
mfv(mySamples)[1]
。这里的数字1
很重要,因为它实际上返回了最频繁出现的值们。 - atomiculesmfv(mySamples)
。 - petzi我认为Ken Williams在上面的帖子中写得很好,我添加了几行以处理NA值并将它变成了一个函数以便于使用。
我发现Ken Williams在上面的帖子中写得很好,我添加了几行代码来解决缺失值问题,并将其转换为一个函数,以方便使用。
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)))])
}
一种快速而简单的估算连续单变量分布(例如正态分布)中的向量模式的方法是定义并使用以下函数:
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
set.seed(1);a<-runif(100);mode<-density(a)$x[which.max(density(a)$y)];abline(v=mode)
- Jotaerror in density.default(x, from = from, to = to) : need at least 2 points to select a bandwidth automatically
- Sergiodensity
时需要手动设置带宽。然而,如果你只有一个数据点,那么该数据点的值很可能就是你对于众数的最佳猜测... - Rasmus Bååthestimate_mode <- function(x) { if (length(x)>1){ d <- density(x) d$x[which.max(d$y)] }else{ x } }
我正在测试一种估计主导风向的方法,而不是使用圆形包中的矢量平均方向。我正在处理多边形等级上的点,因此有时只有一个具有方向的点。谢谢! - Sergiomodeav <- 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()
}
method = 'modes'
出现相等的次数时。然后函数返回所有唯一的值,但实际上没有众数,所以应该返回 NA
。我会添加另一个答案,其中包含稍微优化过的函数版本,感谢你的启发! - hugovdberg这里,另一个解决方案:
freq <- tapply(mySamples,mySamples,length)
#or freq <- table(mySamples)
as.numeric(names(freq)[which.max(freq)])
na.rm
和 return_multiple
。names()
的答案不同,此答案在返回值中保持了 x
的数据类型。stat_mode <- function(x, return_multiple = TRUE, na.rm = FALSE) {
if(na.rm){
x <- na.omit(x)
}
ux <- unique(x)
freq <- tabulate(match(x, ux))
mode_loc <- if(return_multiple) which(freq==max(freq)) else which.max(freq)
return(ux[mode_loc])
}
foo <- c(2L, 2L, 3L, 4L, 4L, 5L, NA, NA)
bar <- c('mouse','mouse','dog','cat','cat','bird',NA,NA)
str(stat_mode(foo)) # int [1:3] 2 4 NA
str(stat_mode(bar)) # chr [1:3] "mouse" "cat" NA
str(stat_mode(bar, na.rm=T)) # chr [1:2] "mouse" "cat"
str(stat_mode(bar, return_mult=F, na.rm=T)) # chr "mouse"
基于 @Chris 的函数来计算众数或相关指标,然而使用 Ken Williams 的方法来计算频率。这个函数为没有众数的情况提供了修复(所有元素同样频繁),并且提供了一些更易读的 方法
名称。
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的帖子作为基准,我对之前的一些答案进行了基准测试,以展示我的函数在性能上与Ken的函数接近,各种输出选项的条件语句仅会导致轻微的开销:
pracma
包?据我所知,1.9.3 版本有完全不同的实现。 - hugovdbergstop
而不是 warning
,因为该函数没有任何有意义的返回值。 - Gregor Thomascollapse
包中的通用函数fmode
现已在CRAN上提供,它实现了基于索引哈希的C++模式。它比上述任何方法都要快得多。它附带有向量、矩阵、数据框和dplyr分组tibbles的方法。语法:
library(collapse)
fmode(x, g = NULL, w = NULL, ...)
其中x
可以是上述对象之一,g
提供一个可选的分组向量或分组向量列表(用于在C++中执行分组模式计算),w
(可选)提供一个数字权重向量。在分组tibble方法中,没有g
参数,您可以使用data %>% group_by(idvar) %>% fmode
。
mode
和函数class
是相同的? - Corey Levinson