在R中,mean()和median()是标准函数,它们执行您所期望的功能。Mode()告诉您对象的内部存储模式,而不是参数中出现次数最多的值。但是是否存在一个标准库函数来实现向量(或列表)的统计模式?
当前回答
我还不能投票,但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)]
}
我们知道你可能根本不想约束你的分布,那么设置from=-"BIG NUMBER", to="BIG NUMBER"
其他回答
在我看来,如果一个集合有一个模式,那么它的元素就可以与自然数一一对应。因此,查找模式的问题简化为生成这样一个映射,查找映射值的模式,然后映射回集合中的一些项。(处理NA发生在映射阶段)。
我有一个直方图函数,它的原理类似。(本文代码中使用的特殊函数和操作符应在Shapiro和/或neatOveRse中定义。在此复制夏皮罗和奈尔斯的部分是经过允许的;复制的片段可根据本网站的条款使用。)直方图的伪代码是
.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,但返回一个向量的所有绝对最大值。maxloc的R伪代码是
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
Then
imode <- histogram %O% maxloc
and
x %|% map %|% imode %|% unmap
将计算任何集合的模式,只要定义了适当的映射-ping和取消映射-ping函数。
为了生成模式,我写了下面的代码。
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)
对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])
}
要显示它与可选参数一起工作并维护数据类型:
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的简化。
对此有多种解决方案。我检查了第一个,然后写了我自己的。把它贴在这里,如果它能帮助到任何人:
Mode <- function(x){
y <- data.frame(table(x))
y[y$Freq == max(y$Freq),1]
}
让我们用几个例子来测试一下。我正在取虹膜数据集。让我们用数值数据进行测试
> Mode(iris$Sepal.Length)
[1] 5
你可以验证这是正确的。
现在虹膜数据集中唯一的非数字字段(Species)没有模式。让我们用我们自己的例子进行测试
> test <- c("red","red","green","blue","red")
> Mode(test)
[1] red
EDIT
正如注释中提到的,用户可能希望保留输入类型。在这种情况下,mode函数可以修改为:
Mode <- function(x){
y <- data.frame(table(x))
z <- y[y$Freq == max(y$Freq),1]
as(as.character(z),class(x))
}
函数的最后一行只是将最终的模式值强制为原始输入的类型。
下面的函数有三种形式:
method = "mode"[默认值]:计算单模态向量的模式,否则返回NA Method = "nmodes":计算vector中模式的个数 Method = "modes":列出单模态或多模态向量的所有模态
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()
}