在数据框中找到最常见的值组合

7

我希望找到数据框中最常见的数值组合。

以下是示例数据:

dat <- data.frame(age=c(50,55,60,50,55),sex=c(1,1,1,0,1),bmi=c(20,25,30,20,25))

在这个例子中,我想要的结果是年龄=55、性别=1和BMI=25的组合,因为这是列值最频繁的组合。
我的真实数据有大约30000行和20列。有什么高效的方法可以在这30000个观察值中找到这20个值的最常见组合吗?
非常感谢!
4个回答

10

以下是使用 data.table 的方法:

dt <- data.table(dat)
setkeyv(dt, names(dt))
dt[, .N, by = key(dt)]
dt[, .N, by = key(dt)][N == max(N)]
#    age sex bmi N
# 1:  55   1  25 2

以下是基于 R 语言的方法:

x <- data.frame(table(dat))
x[x$Freq == max(x$Freq), ]
#    age sex bmi Freq
# 11  55   1  25    2

我不知道这两种方法的扩展性如何,特别是如果组合的数量将会很大。因此,请测试并反馈结果!


如果你只对一行结果感兴趣,用which.max(x$Freq)替换x$Freq == max(x$Freq),用which.max(N)替换N == max(N)


感谢您的解释!data.table方法完美地运行,并且非常快速(在我的30000 * 20个数据上只需0.31秒),然而,基本的R方法在我的数据上无法工作,因为组合数确实太大了,超出了table()的处理能力。 - Rob
刚刚尝试了你建议的 dt[, .N, by = key(dt)][N == which max(N)] 来获取一行数据,但是这给我返回了和 dt[, .N, by = key(dt)][N == max(N)] 相同的结果... 有什么建议可以只获取最常见的值组合的一行数据吗? - Rob
@Rob,应该是dt[, .N, by = key(dt)][which.max(N)] - A5C1D2H2I1M1N2O1R2T1

2

简单而快捷的解决方案。我确信有更高级的方法,使用plyr包或类似的工具。

> (tab <- table(apply(dat, 1, paste, collapse=", ")))
50, 0, 20 50, 1, 20 55, 1, 25 60, 1, 30 
        1         1         2         1 

> names(which.max(tab))
[1] "55, 1, 25"

table(do.call(paste, dat)) 也可以奏效。不确定它与 apply(...) 在速度方面的比较如何。 - A5C1D2H2I1M1N2O1R2T1
谢谢,完美运作!do.call似乎比apply方法快一点(2.00秒 vs 2.58秒)。 - Rob
这可能是因为在我的apply解决方案中,paste在每一行上都被调用了,但在do.call解决方案中只被调用了一次。不过我很高兴你最终选择了@AnandaMahto的答案,这绝对是正确的方法。 - Backlin

1
类似这样吗?
> dat[duplicated(dat), ]
  age sex bmi
5  55   1  25

使用 while 循环(可能会耗时)

这里有另一个数据框,其中有超过1个重复的案例。

> dat <- data.frame(age=c(50,55,60,50,55, 55, 60),
                   sex=c(1,1,1,0,1, 1,1),
                   bmi=c(20,25,30,20,25, 25,30))
> dat[duplicated(dat), ] # see data.frame
      age sex bmi
    5  55   1  25
    6  55   1  25
    7  60   1  30


# finding the most repeated item
> while(any(duplicated(dat))){
   dat <- dat[duplicated(dat), ]
   #print(dat)
 }

> print(dat)
  age sex bmi
6  55   1  25

1
这里有一个tidyverse的解决方案。按照所有变量分组并获取每个组的计数具有优点,即您可以查看所有其他组的计数,而不仅仅是最大值。
library(tidyverse)
dat <- data.frame(age=c(50,55,60,50,55),sex=c(1,1,1,0,1),bmi=c(20,25,30,20,25))
dat %>%
  group_by_all() %>%
  summarise(count = n()) %>%
  arrange(desc(count))
#> # A tibble: 4 x 4
#> # Groups:   age, sex [4]
#>     age   sex   bmi count
#>   <dbl> <dbl> <dbl> <int>
#> 1    55     1    25     2
#> 2    50     0    20     1
#> 3    50     1    20     1
#> 4    60     1    30     1

这段内容意为:2018年10月17日,使用reprex package(版本0.2.0)创建。


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