2014-05-05 42 views
1

我有一个data.frame tr_id_cat由两列组成:id,category。R--快速计数数据帧行的方法,两列设置为特定值

  • tr_id_cat有15万
  • ID有30万个唯一值
  • 类别有20个独特的价值观

我想建立一个计数矩阵:

我的代码远,但它需要年龄:

# id and categories are lists of the possible values (dictionary) 
nb_id = length(id) 
nb_categories = length(categories) 
COUNT_ID_CATEGORY = array(0, dim=c(nb_id,nb_categories)) 

for(i in (1:nb_categories)) 
{ 
    cat_ = categories[i] 
    subs = tr_id_cat[ tr_id_cat$category == cat_ ,] 

    for(j in(1:dim(subs)[1])) 
    { 
     id_ = subs$id[j] 
     id_idx = which(id == id_) 
     COUNT_ID_CATEGORY[id_idx,cat_idx] = dim(subs[ subs$id == id_,])[1]; 
    } 
} 

小版的什么,我试图做的:

id, category 
1, 1 
1, 1 
1, 1 
1, 2 
1, 2 
2, 1 
3, 1 

将被转换成数矩阵:

COUNT_ID_CATEGORY[1,1] = 3 # first three lines 
COUNT_ID_CATEGORY[1,2] = 2 # line 4 and 5 
COUNT_ID_CATEGORY[2,1] = 1 
COUNT_ID_CATEGORY[2,2] = 0 
COUNT_ID_CATEGORY[3,1] = 1 
COUNT_ID_CATEGORY[3,2] = 0 
etc 
+0

你尝试dplyr或data.table方法?你能提供一个你的数据集和期望输出的最小例子吗? –

回答

2

使用data.tablereshape2的解决方案。

library(data.table) 
library(reshape2) 

# Number of rows 
n <- 15e6 

# Generate test data 
tr_id_cat <- data.table(id = ceiling(runif(n) * 300e3), 
         category = ceiling(runif(n) * 20)) 

# set keys 
setkey(tr_id_cat, id, category) 

# count 
tab <- tr_id_cat[, .N, keyby = list(id, category)] 

# reshape as array 
dcast.data.table(tab, id ~ category, value.var = "N", fill = 0L) 

这里我已经添加了@Arun的解决方案。而且我还添加了时间结果。看来Arun的解决方案需要大约20%的时间。

library(data.table) 
library(reshape2) 
library(rbenchmark) 

f1 <- function(n = 15e6) { 
    tr_id_cat <- data.table(id = ceiling(runif(n) * 300e3), 
          category = ceiling(runif(n) * 20)) 
    setkey(tr_id_cat, id, category) 
    tab <- tr_id_cat[, .N, keyby = list(id, category)] 
    dcast.data.table(tab, id ~ category, value.var = "N", fill = 0L) 
} 

f2 <- function(n = 15e6) { 
    tr_id_cat <- data.table(id = ceiling(runif(n) * 300e3), 
          category = ceiling(runif(n) * 20)) 
    tab <- tr_id_cat[, .N, by = list(id, category)] 
    dcast.data.table(tab, id ~ category, value.var = "N", fill = 0L) 
} 

benchmark(f1(), f2(), 
      columns = c("test", "replications", "elapsed", "relative"), 
      replications = rep(10, 3)) 

我的机器上结果:

test replications elapsed relative 
1 f1()   10 61.62 1.000 
3 f1()   10 62.21 1.010 
5 f1()   10 61.60 1.000 
2 f2()   10 73.55 1.194 
4 f2()   10 74.31 1.206 
6 f2()   10 73.33 1.190 
+0

这看起来很完美。非常感谢你! – tucson

+1

'data.table'有它自己的'dcast',可能比'reshape2'快得多 –

+0

谢谢@DavidArenburg!我以为我使用data.table中的'dcast',但我没有。因为'data.table'中的'dcast'不是S3通用的。已应用更正。 – djhurio

-1

东西这么简单?

d <- data.frame(category = rep(c(1:3), 3), 
       id = rep(c(1:3), 3)) 
d$tr_id_cat <- with(d, paste0(category, id)) 

library(plyr) 
ddply(d, .(tr_id_cat), summarise, n=length(tr_id_cat)) 

,或者服用d没有tr_id_cat变量

plyr::count(d, .(category, id)) 

或dplyr

library(dplyr) 
d %.% 
    dplyr:::group_by(tr_id_cat) %.% 
    dplyr:::summarise(n = length(tr_id_cat)) 
+1

我不认为他有tr_id_cat作为单独的列 – iugrina

+0

我不明白这个-1。所有建议的解决方案都可以正常工作,无论是否有额外的tr_id_cat列。 –

2

如果我正确理解你的问题,你想获得这样的事情

library(dplyr) 
tr_id_cat %.% group_by(id,category) %.% summarise(n=n()) 
+0

它可能是最快的方法? – droopy

+0

我看不出它的工作原理。你可以添加数据结构吗?好的,tr_id_cat是data.frame。 –

相关问题