2016-08-24 20 views
0

我有一个数据帧times,看起来像这样:R:如何使用dplyr作为替代聚集

user  time 
A  7/7/2010 
B  7/12/2010 
C  7/12/2010 
A  7/12/2010 
C  7/15/2010 

我使用aggregate(time ~ user, times, function(x) sort(as.vector(x)))得到这个:

user  time 
A  c(7/7/2010, 7/12/2010) 
B  c(7/12/2010) 
C  c(7/12/2010, 7/15/2010) 

的问题是,我在times有超过2000万条目,所以aggregate超过4小时。有没有其他方法可以使用dplyr来获得排序的日期向量?

+4

这对'data.table'很重要,例如, 'setDT(times)[,。(time = list(sort(time))),by =“user”]'。 – nrussell

回答

3

更新答:基于您的评论,这个怎么样:

library(dplyr) 

# Data (with a few additions) 
times = read.table(text="user  time 
A  7/7/2010 
B  7/12/2010 
B 7/13/2010 
C  7/12/2010 
A  7/12/2010 
A 7/13/2010 
C  7/15/2010", header=TRUE, stringsAsFactors=FALSE) 

times$time = as.Date(times$time, "%m/%d/%Y") 

times 
user  time 
1 A 2010-07-07 
2 B 2010-07-12 
3 B 2010-07-13 
4 C 2010-07-12 
5 A 2010-07-12 
6 A 2010-07-13 
7 C 2010-07-15 
times %>% group_by(user) %>% 
    summarise(First=min(time), 
      Last=max(time), 
      N = n(), 
      minDiff=min(diff(time)), 
      meanDiff=mean(diff(time)), 
      NumDiffUniq = length(unique(diff(time)))) 
user  First  Last  N  minDiff  meanDiff NumDiffUniq 
1  A 2010-07-07 2010-07-13  3   1 days   3 days   2 
2  B 2010-07-12 2010-07-13  2   1 days   1 days   1 
3  C 2010-07-12 2010-07-15  2   3 days   3 days   1 

或者iginal回答:

我不清楚你想完成什么。如果你只是想进行排序您的数据帧,然后用dplyr你会怎么做:

library(dplyr) 

times.sorted = times %>% arrange(user, time) 

如果你想time成为日期为每个user的字符串,那么你可以做:

times.summary = times %>% group_by(user) %>% 
    summarise(time = paste(time, collapse=",")) 

但请注意,对于每个用户,这将导致包含日期的单个字符串。

times.summary 
user    time 
1  A 7/7/2010,7/12/2010 
2  B   7/12/2010 
3  C 7/12/2010,7/15/2010 

如果你真的想每个单元是日期的一个载体,可以使每一个小区的名单(虽然有可能是一个更好的办法)。例如:

times.new = times %>% group_by(user) %>% 
    summarise(time = list(as.vector(time))) 

times.new$time 
[[1]] 
[1] "7/7/2010" "7/12/2010" 

[[2]] 
[1] "7/12/2010" 

[[3]] 
[1] "7/12/2010" "7/15/2010" 

但是,如果你的目标是按组来分析数据,那么你实际上并不需要做任何以上的。您可以使用基数,dplyrdata.table函数按组进行任何分析,而无需先对数据进行排序。

+0

谢谢,这个非常有用。我应该更清楚我想完成什么。最后,我想拥有一个包含以下变量的数据集: user |第一次|上次|总时间| min时间之差|时间之间的平均差异|都是相同的时间差异(真/假) 我设法使用聚合在较小的样本上创建类似的东西。但有了20M的用户总计需要4个多小时。 –

+0

查看更新并让我知道它是否符合您的需求。 – eipi10

+0

更新后的答案比我使用'aggregate'的原始代码快得多。挑战仍然是运行时间。更新后的答案中的代码花费了不到一分钟的时间才能在具有128G RAM的计算机上运行1000个条目。如果我找不到更有效的解决方案,我可能会考虑运行几个星期。我相信我可能需要在sql中重新创建这个查询。 –

0

基于由eipi10dplyr溶液和nrussell的建议,我已经写了使用data.table以下解决方案。

首先,你需要的变量times格式:

times$time = as.Date(times$time, "%m/%d/%Y") 

那么你就需要使用到times转换为data.table:

library(data.table) 
times <- as.data.table(times) 

改写times是我的目的是有用的,但你可能想要实例化一个新的变量。格式化你的数据帧作为data.table后只是做:

new.times <- times[, 
        .(first = min(time), 
         last = max(time), 
         n = .N, 
         meandiff = mean(diff(time)), 
         mindiff = min(diff(time)), 
         numdiffuniq = length(unique(diff(time))), 
         by='user')] 

运行与128G内存的Linux虚拟机上,并使用1000个entires样本,经过运行时间为0.43s。

有关data.table的更多信息,请参阅this tutorial