计算值的唯一组合

Posted

技术标签:

【中文标题】计算值的唯一组合【英文标题】:count unique combinations of values 【发布时间】:2012-02-10 08:05:43 【问题描述】:

我的数据框如下所示:

ID | value 1 | value 2 | value 3 | value 4
1  |    M    |    D    |    F    |   A
2  |    F    |    M    |    G    |   B
3  |    M    |    D    |    F    |   A
4  |    L    |    D    |    E    |   B

我想要这样的东西。

value 1 | value 2 | value 3 | value 4|  Number of combinations
  M     |    D    |    F    |   A    |     2
  F     |    M    |    G    |   B    |     1
  L     |    D    |    E    |   B    |     1

例如计算列值 1 - 值 4 的唯一组合数。

【问题讨论】:

【参考方案1】:

plyr 包中的count 将完成该任务。

> df
  ID   value.1   value.2   value.3 value.4
1  1     M         D         F           A
2  2     F         M         G           B
3  3     M         D         F           A
4  4     L         D         E           B
> library(plyr)
> count(df[, -1])
    value.1   value.2   value.3 value.4 freq
1     F         M         G           B    1
2     L         D         E           B    1
3     M         D         F           A    2

【讨论】:

【参考方案2】:
N <- 10000

d <- data.frame(
  ID=seq(1, N), 
  v1=sample(c("M","F", "M", "L"), N, replace = TRUE), 
  v2=sample(c("D","M","D","D"), N, replace = TRUE), 
  v3=sample(c("F","G","F","E"), N, replace = TRUE),
  v4=sample(c("A","B","A","B"), N, replace = TRUE)
)

有data.table(最快)

dt <- data.table::as.data.table(d)
dt[, .N, by = c('v1','v2','v3','v4')]

使用 dplyr

dplyr::count_(d, vars = c('v1','v2','v3','v4'))

使用 plyr

plyr::count(d, vars = c('v1','v2','v3','v4'))
plyr::ddply(d, .variables = c('v1','v2','v3','v4'), nrow)

有聚合(最慢)

aggregate(ID ~ ., d, FUN = length)

基准测试

microbenchmark::microbenchmark(dt[, .N, by = c('v1','v2','v3','v4')],
                               plyr::count(d, vars = c('v1','v2','v3','v4')),
                               plyr::ddply(d, .variables = c('v1','v2','v3','v4'), nrow),
                               dplyr::count_(d, vars = c('v1','v2','v3','v4')),
                               aggregate(ID ~ ., d, FUN = length), 
                               times = 1000)

Unit: microseconds
                                                         expr      min       lq      mean   median        uq        max neval  cld
                     dt[, .N, by = c("v1", "v2", "v3", "v4")]  887.807 1107.543  1263.777 1174.258  1289.724   4263.156  1000 a   
             plyr::count(d, vars = c("v1", "v2", "v3", "v4")) 3912.791 4270.387  5379.080 4498.053  5791.743 157146.103  1000   c 
 plyr::ddply(d, .variables = c("v1", "v2", "v3", "v4"), nrow) 7737.874 8553.370 10630.849 9018.266 11126.517 187301.696  1000    d
           dplyr::count_(d, vars = c("v1", "v2", "v3", "v4")) 2126.913 2432.957  2763.499 2568.251  2789.386  12549.669  1000  b  
                           aggregate(ID ~ ., d, FUN = length) 7395.440 8121.828 10546.659 8776.371 10858.263 210139.759  1000    d

似乎最好简单地使用data.table 而不是data.frame,因为它是最快的并且不需要其他函数或库来计算。另请注意,aggregate 函数在大型数据集上的执行速度要慢得多。

最后一点:随时更新新方法。

【讨论】:

我认为您应该显示更大数据集的结果。另外,在查看args(plyr::count) 之后,我猜plyr::count(d, c('v1','v2','v3','v4')) 可能是正确的。可能还有一个dplyr::count 可以考虑。 @Frank,它现在基于 10k 行。 好的,谢谢。另一点:length(ID) 现在似乎不会给出正确的结果,因为ID 重复值。测试方法间结果的相等性通常是一个好主意。哦,没关系,我想它有什么价值并不重要。 Fwiw,data.table 速度快的原因记录在?GForce 它们给出了不同的格式,但 tapply(d$ID, d[, -1], length)table(d[, -1]) 在这种特殊情况下也很快。【参考方案3】:

没有 plyr。

aggregate(ID ~ ., d, FUN=length)# . means all variables in d except ID

【讨论】:

不错,但与 plyr::count 相比非常 (!!) 慢。从 microbenchmark 测试,4000x500 DF 总结 3 列的频率,似乎 count 快 20 倍(!)。【参考方案4】:

这里是使用plyr 包的解决方案

library(plyr)
d <- data.frame(
    ID=seq(1,4), v1=c("M","F", "M", "L"), 
    v2=c("D","M","D","D"), v3=c("F","G","F","E"), v4=c("A","B","A","B")
)
ddply(d,.(v1,v2,v3,v4), nrow)

我希望这不是家庭作业...

【讨论】:

以上是关于计算值的唯一组合的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历数据框:计算每个唯一变量的值的每个成对组合。

在计算之前删除包含某些值的组合

计算 Pandas 中具有相同列值的行的平均值

计算每个唯一值的出现次数

如何计算明细表中的唯一组合?

困惑:我有 3 个空格(组合)和 3 个分类值。如何计算值的所有组合?