按组计算最常见的值(众数)

11

我正在尝试按组查找最常见的值。在以下示例数据框中:

df<-data.frame(a=c(1,1,1,1,2,2,2,3,3),b=c(2,2,1,2,3,3,1,1,2))  
> df  
  a b  
1 1 2  
2 1 2  
3 1 1  
4 1 2  
5 2 3  
6 2 3  
7 2 1  
8 3 1  
9 3 2  

我想添加一个名为'c'的列,该列应显示按'a'分组时'b'的最常出现的值。 我希望输出以下结果:

> df  
  a b c  
1 1 2 2    
2 1 2 2    
3 1 1 2    
4 1 2 2    
5 2 3 3    
6 2 3 3    
7 2 1 3    
8 3 1 1   
9 3 2 1    

我试过使用table和tapply,但是没有做对。有没有快速的方法可以实现这个?
谢谢!


3
这与 此链接 非常相关。 - David Arenburg
3个回答

16

在David的评论基础上,你的解决方案如下:

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

library(dplyr)
df %>% group_by(a) %>% mutate(c=Mode(b))

注意,当df$a3时,b的众数是1


8

我们可以使用 ave 按 'a' 分组,并获取 'b' 的“Mode”。

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

df$c <-  with(df, ave(b, a, FUN=Mode))
df$c
#[1] 2 2 2 2 3 3 3 1 1

或者使用data.table

library(data.table)
setDT(df)[, c:= Mode(b), by=a][]

1
谢谢@akrun!为了从mode函数中排除NAs,请将第二行更改为“ux <- unique(x[!is.na(x)])”。 - WalterB

1
这里有一个基于R语言的方法,使用table计算交叉表,max.col找到每个组的众数,再利用reprle填充跨组的众数。请保留HTML标签。
# calculate a cross tab, frequencies by group
myTab <- table(df$a, df$b)
# repeat the mode for each group, as calculated by colnames(myTab)[max.col(myTab)] 
# repeating by the number of times the group ID is observed
df$c <- rep(colnames(myTab)[max.col(myTab)], rle(df$a)$length)

df
  a b c
1 1 2 2
2 1 2 2
3 1 1 2
4 1 2 2
5 2 3 3
6 2 3 3
7 2 1 3
8 3 1 2
9 3 2 2

请注意,这假定数据已按组进行排序。此外,默认值max.col是随机打破平局(多种模式)。如果你想让第一个或最后一个值成为模式,可以使用ties.method参数来设置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接