我想计算data.frame中的所有组合。
数据看起来像这样
9 10 11 12
1 1 1 1 1
2 0 0 0 0
3 0 0 0 0
4 1 1 1 1
5 1 1 1 1
6 0 0 0 0
7 1 0 0 1
8 1 0 0 1
9 1 1 1 1
10 1 1 1 1
我想要的输出只是
comb n
1 1 1 1 5
0 0 0 0 3
1 0 0 1 2
你知道有什么简单的功能吗?
谢谢
dt = structure(list(`9` = c(1, 0, 0, 1, 1, 0, 1, 1, 1, 1), `10` = c(1,
0, 0, 1, 1, 0, 0, 0, 1, 1), `11` = c(1, 0, 0, 1, 1, 0, 0, 0,
1, 1), `12` = c(1, 0, 0, 1, 1, 0, 1, 1, 1, 1)), .Names = c("9",
"10", "11", "12"), class = "data.frame", row.names = c(NA, -10L
))
答案 0 :(得分:11)
带有aggregate
的基础R解决方案:
aggregate(seq(nrow(dt))~., data=dt, FUN=length)
# 9 10 11 12 seq(nrow(dt))
#1 0 0 0 0 3
#2 1 0 0 1 2
#3 1 1 1 1 5
修改强>
为了让colnames更符合你的输出,你可以这样做:
`colnames<-`(aggregate(seq(nrow(dt))~., data=dt, FUN=length), c("c", "o", "m", "b", "n"))
# c o m b n
#1 0 0 0 0 3
#2 1 0 0 1 2
#3 1 1 1 1 5
或者,更短:
aggregate(cbind(n = 1:nrow(dt))~., dt, length)
# 9 10 11 12 n
#1 0 0 0 0 3
#2 1 0 0 1 2
#3 1 1 1 1 5
答案 1 :(得分:9)
我们可以使用data.table
或dplyr
。这些非常有效。我们将'data.frame'转换为'data.table'(setDT(dt)
),按'dt'(names(dt)
)的所有列进行分组,得到nrow(.N
)作为'伯爵'
library(data.table)
setDT(dt)[,list(Count=.N) ,names(dt)]
或者我们可以使用dplyr
使用类似的方法。
library(dplyr)
names(dt) <- make.names(names(dt))
dt %>%
group_by_(.dots=names(dt)) %>%
summarise(count= n())
如果有人想查看某些指标(并且还要提前备份我的声明(efficient!
)),
set.seed(24)
df1 <- as.data.frame(matrix(sample(0:1, 1e6*6, replace=TRUE), ncol=6))
akrunDT <- function() {
as.data.table(df1)[,list(Count=.N) ,names(df1)]
}
akrunDplyr <- function() {
df1 %>%
group_by_(.dots=names(df1)) %>%
summarise(count= n())
}
cathG <- function() {
aggregate(cbind(n = 1:nrow(df1))~., df1, length)
}
docendoD <- function() {
as.data.frame(table(comb = do.call(paste, df1)))
}
deena <- function() {
table(apply(df1, 1, paste, collapse = ","))
}
以下是microbenchmark
结果
library(microbenchmark)
microbenchmark(akrunDT(), akrunDplyr(), cathG(), docendoD(), deena(),
unit='relative', times=20L)
# Unit: relative
# expr min lq mean median uq max neval cld
# akrunDT() 1.000000 1.000000 1.000000 1.00000 1.000000 1.0000000 20 a
# akrunDplyr() 1.512354 1.523357 1.307724 1.45907 1.365928 0.7539773 20 a
# cathG() 43.893946 43.592062 37.008677 42.10787 38.556726 17.9834245 20 c
# docendoD() 18.778534 19.843255 16.560827 18.85707 17.296812 8.2688541 20 b
# deena() 90.391417 89.449547 74.607662 85.16295 77.316143 34.6962954 20 d
答案 2 :(得分:6)
您可以仅使用基础R尝试以下方法:
as.data.frame(table(comb = do.call(paste, dt)))
# comb Freq
#1 0 0 0 0 3
#2 1 0 0 1 2
#3 1 1 1 1 5
答案 3 :(得分:5)
也许那样:table(apply(dt, 1, paste, collapse = ","))
答案 4 :(得分:3)
同样在基地R:
使用public function FormattedComments()
{
return $this->hasOne('App\Models\StoreComment','StoreID','StoreID')
->join('users','StoreComment.created_by','=','users.UserID')
->select(DB::raw("group_concat(DATE_FORMAT(StoreComment.created_at,'%Y-%m-%d'), ' - ', Comment, ' - ', ShortName, '\n' ORDER BY StoreComment.created_at DESC SEPARATOR '')"))
->groupBy('StoreID')
->whereNull('StoreComment.deleted_at')
->orderBy('StoreComment.created_at','DESC');
}
获取唯一组合列表。
unique.matrix
然后进行比较并计算:
uncs <- unique.matrix(as.matrix(df), MARGIN = 1)
答案 5 :(得分:1)
使用 group_by_all() 可以更轻松地完成上述 dplyr 解决方案...
dt %>% group_by_all %>% count
...据我所知,它已被 cross() 方法取代。添加一些排序,你会得到:
dt %>% group_by(across()) %>% count %>% arrange(desc(n))
> dt %>% group_by(across()) %>% count %>% arrange(desc(n))
# A tibble: 3 x 5
# Groups: 9, 10, 11, 12 [3]
`9` `10` `11` `12` n
<dbl> <dbl> <dbl> <dbl> <int>
1 1 1 1 1 5
2 0 0 0 0 3
3 1 0 0 1 2
如果您愿意,您可以将其转换为矩阵。