计算值的唯一组合
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)
我希望这不是家庭作业...
【讨论】:
以上是关于计算值的唯一组合的主要内容,如果未能解决你的问题,请参考以下文章