2016-08-24 45 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