按组创建一个变量,记录最常出现的值

7

定义:

df1 <-data.frame(
id=c(rep(1,3),rep(2,3)),
v1=as.character(c("a","b","b",rep("c",3)))
)

s.t.

> df1
  id v1
1  1  a
2  1  b
3  1  b
4  2  c
5  2  c
6  2  c

我想创建一个第三个变量freq,它包含按id分类的变量v1中最常见的观测值。
> df2
  id v1 freq
1  1  a    b
2  1  b    b
3  1  b    b
4  2  c    c
5  2  c    c
6  2  c    c

1
ID组内的关系应该如何处理? - Chase
@Chase 在我的情况下,我确定没有任何关联。 - Fred
好问题关于打结,我会记录一下我的解决方案如何处理它... - joran
3个回答

3
您可以使用 ddply 和自定义函数来选择最常见的值:
myFun <- function(x){
    tbl <- table(x$v1)
    x$freq <- rep(names(tbl)[which.max(tbl)],nrow(x))
    x
}

ddply(df1,.(id),.fun=myFun)

请注意,which.max将返回最大值的第一次出现,如果存在并列,则会返回第一次出现的位置。如需在并列时随机打破,请参见nnet包中的??which.is.max选项。

3

另一种方法是使用tidyverse函数:

  • 首先进行分组,使用group_by(),并计算第二个变量的出现次数,使用tally()
  • 使用arrange()按出现次数排序
  • 使用summarize()first()进行汇总并选择第一行

因此:

df1 %>%
group_by(id, v1) %>%
tally() %>%
arrange(id, desc(n)) %>%
summarize(freq = first(v1))

这将给你一个简单明了的映射表(我认为更加清晰):
# A tibble: 2 x 2
     id   freq
  <dbl> <fctr>
1     1      b
2     2      c

然后,您可以使用 left_join 将原始数据帧与该表连接。


我喜欢这种方法,因为在 tally() 之后可以检查和识别并列情况。@joran 的函数或许也能实现这个功能,但对于我来说不如这种方法直观。 - tjebo

1
mode <- function(x) names(table(x))[ which.max(table(x)) ]
df1$freq <- ave(df1$v1, df1$id, FUN=mode)
> df1
  id v1 freq
1  1  a    b
2  1  b    b
3  1  b    b
4  2  c    c
5  2  c    c
6  2  c    c

我认为 df2 是一个笔误,当我运行这个程序时,id=2 的值会变成 NA - joran
笔误已经消失了,但我仍然不认为这段代码有效。当id=2时,max(table(x))返回3,但table(x)只有一个名称,因此您的函数mode返回NA。 - joran
它是偶然给出了正确的结果,因为有些因素的意外。df$id是一个因子,第三个级别是“c”。已修复。 - IRTFM

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