在 data.frame 中查找最常见的值组合

Posted

技术标签:

【中文标题】在 data.frame 中查找最常见的值组合【英文标题】:Find most frequent combination of values in a data.frame 【发布时间】:2013-09-05 09:09:28 【问题描述】:

我想在 data.frame 中找到最常见的值组合。

以下是一些示例数据:

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

在此示例中,我要查找的结果是 age=55、sex=1 和 bmi=25 的组合,因为这是最常见的列值组合。

我的真实数据大约有 30000 行和 20 列。在 30000 个观测值中找到这 20 个值的最常见组合的有效方法是什么?

非常感谢!

【问题讨论】:

【参考方案1】:

这是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

不过,我不知道这两种方法的规模如何,尤其是在组合数量很大的情况下。所以,回来测试并报告!


如果您真的只对一行结果感兴趣,请将x$Freq == max(x$Freq) 替换为which.max(x$Freq) 并将N == max(N) 替换为which.max(N)

【讨论】:

感谢您的解释! data.table 方法运行良好且速度非常快(在我自己的 30000*20 数据上为 0.31 秒),但是,基本 R 方法不适用于我自己的数据,因为组合的数量对于表格来说确实太大了()。 刚试过dt[, .N, by = key(dt)][N == which max(N)]你建议只得到一行,但这给了我同样的结果dt[, .N, by = key(dt)][N == max(N)]...关于如何用最常见的组合只得到一行的任何建议价值观? @Rob,应该是dt[, .N, by = key(dt)][which.max(N)]【参考方案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(...) 谢谢,完美运行! do.call 似乎比 apply 方法快一点(2.00 秒对 2.58 秒)。 这可能是因为在我的apply 解决方案中,paste 在每一行都被调用,但在do.call 解决方案中它只被调用一次。不过,我很高兴您选择了@AnandaMahto 的答案,这绝对是要走的路。【参考方案3】:

这样的??

> dat[duplicated(dat), ]
  age sex bmi
5  55   1  25

使用while(可能很耗时)

这是另一个重复超过 1 个案例的 data.frame

> 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

【讨论】:

【参考方案4】:

这是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

由reprex package (v0.2.0) 于 2018 年 10 月 17 日创建。

【讨论】:

以上是关于在 data.frame 中查找最常见的值组合的主要内容,如果未能解决你的问题,请参考以下文章

如何用(data.frame)查找表中的值标签替换数据框中的数字代码?

按组划分的最常见值(模式)[重复]

在 SQL 列中查找最常见的值

在 data.frame 中查找字符串

在SQLAlchemy中查找数组列中最常见的值

如何在 R data.frame 中查找和删除所有缺少数据的行块?