2010-04-15 77 views
2

(我今天早些時候試過問這個問題,但後來意識到我過分簡化了問題;我收到的答案是正確的,但我無法使用他們是因爲在原來的問題的問題我過於簡單化這是我第2次嘗試...)在R中的數據框中總結分組記錄(...再次)

我有一個數據幀R中,看起來像:

"Timestamp", "Source", "Target", "Length", "Content" 
0.1  , P1  , P2  , 5  , "ABCDE" 
0.2  , P1  , P2  , 3  , "HIJ" 
0.4  , P1  , P2  , 4  , "PQRS" 
0.5  , P2  , P1  , 2  , "ZY" 
0.9  , P2  , P1  , 4  , "SRQP" 
1.1  , P1  , P2  , 1  , "B" 
1.6  , P1  , P2  , 3  , "DEF" 
2.0  , P2  , P1  , 3  , "IJK" 
... 

,我想轉換這對:

"StartTime", "EndTime", "Duration", "Source", "Target", "Length", "Content" 
0.1  , 0.4  , 0.3  , P1  , P2  , 12  , "ABCDEHIJPQRS" 
0.5  , 0.9  , 0.4  , P2  , P1  , 6  , "ZYSRQP" 
1.1  , 1.6  , 0.5  , P1  , P2  , 4  , "BDEF" 
... 

試圖把這個寫成英文,我想將同一個'源'和'目標'連續記錄在一起,然後打印出每個組的單個記錄,顯示StartTime,EndTime & Duration(= EndTime-StartTime)組以及該組的長度總和,以及該組中的內容(其全部是字符串)的串聯。

在整個數據幀中,TimeOffset值將始終增加。

我看過融化/重鑄,並有一種感覺,它可以用來解決問題,但不能讓我的頭在文檔。我懷疑在R內部可以這樣做,但我真的不知道從哪裏開始。在掐我可以導出數據幀,並在例如Python,但如果可能的話,我寧願留在R中。

預先感謝任何幫助,您可以提供

回答

7

下面是使用plyr另一種解決方案:

id <- with(df1, paste(Source, Target)) 
df1$group <- cumsum(c(TRUE, id[-1] != id[-length(id)])) 

library(plyr) 
ddply(df1, c("group"), summarise, 
    start = min(Timestamp), 
    end = max(Timestamp), 
    content = paste(Content, collapse = ", ") 
) 
+0

喜歡這個解決方案 - 簡單,優雅和完美的作品。謝謝哈德利! – monch1962 2010-04-16 00:37:17

2

試試這個:

id <- as.numeric(gsub("P","",paste(df$Source,df$Target,sep=""))) 
df$id <- cumsum(c(TRUE,diff(id)!=0)) 
res <- by(df, df$id, 
      function(x) { 
      len <- nrow(x) 
      start <- x[1,1] 
      end <- x[len,1] 
      dur <- end - start 
      src <- x[1,2] 
      trg <- x[1,3] 
      len <- sum(x[,4]) 
      cont <- paste(x[,5],collapse="") 
      return(c(start,end,dur,src,trg,len,cont)) 
      } 
     ) 
do.call(rbind,res) 

PS:您需要將結果轉換爲「正確」的格式,最後的結果是一個矩陣的字符串。

2

堅持我的(不優雅)的方式

df1 <- read.table(textConnection(" 
Timestamp Source Target Length Content 
0.1   P1  P2  5  ABCDE 
0.2   P1  P2  3  HIJ 
0.4   P1  P2  4  PQRS 
0.5   P2  P1  2  ZY 
0.9   P2  P1  4  SRQP 
1.1   P1  P2  1  B 
1.6   P1  P2  3  DEF 
2.0   P2  P1  3  IJK 
"),header=T) 

df <- adply(df1, 1 ,transform, newSource = 
as.numeric(paste(substr(Source, 2, 2),substr(Target, 2, 2),sep="")) ) 

ind <- cbind(rle(df$newSource)[[1]],cumsum(rle(df$newSource)[[1]])) 
ind2 <- apply(ind,1,function(x) c(x[2]-(x[1]-1),x[2])) 
res <- ldply(apply(ind2,2,function(x) data.frame(StartTime = df[x[1],1] , 
EndTime = df[x[2],1] , 
Duration = df[x[2],1] - df[x[1],1] , 
Source = df[x[1],2] , 
Target = df[x[1],3] , 
Length=sum(df[x[1]:x[2],4]) , 
Content=paste(df[x[1]:x[2],5],collapse="") 
))) 

    StartTime EndTime Duration Source Target Length  Content 
1  0.1  0.4  0.3  P1  P2  12 ABCDEHIJPQRS 
2  0.5  0.9  0.4  P2  P1  6  ZYSRQP 
3  1.1  1.6  0.5  P1  P2  4   BDEF 
4  2.0  2.0  0.0  P2  P1  3   IJK