2013-01-17 28 views
-1

我有以下的數據幀,R在發生狀態轉換的數據框中查找行?

id, date, state 
1 2012-01-01 a 
1 2012-01-02 a 
1 2012-01-03 a 
1 2012-01-04 b 
1 2012-01-05 b 
2 2013-01-01 a 
2 2013-01-02 a 
2 2013-01-03 b 
2 2013-01-04 b 

每個ID,我想當狀態從a到b以下,我想它插入作爲該ID的列改變到發現的日期。所以上面的例子會收益

id, date, state, changedate 
1 2012-01-01 a 2012-01-03 
1 2012-01-02 a 2012-01-03 
1 2012-01-03 a 2012-01-03 
1 2012-01-04 b 2012-01-03 
1 2012-01-05 b 2012-01-03 
2 2013-01-01 a 2013-01-02 
2 2013-01-02 a 2013-01-02 
2 2013-01-03 b 2013-01-02 
2 2013-01-04 b 2013-01-02 

有沒有辦法通過plyr函數或甚至在基礎R優雅地做到這一點? 在此先感謝。

+3

[你嘗試過什麼?](http://whathaveyoutried.com) – 2013-01-17 23:11:43

+0

@JackManey在這種情況下,例如是最小的,可重複的,這足以爲一個很好的問題。 –

+1

@ sebastian-c根據我的經驗,對SO的看法有所不同。我想你會發現許多人認爲一個簡單的輸入/輸出規範(不管可重複性如何),沒有任何證據表明OP做出了嘗試,是質量低下的問題。理由是,在極端情況下,SO只是成爲一個人們可以自由地爲陌生人完成他們的工作的地方。 – joran

回答

2

編輯:正如塞巴斯蒂安提到的那樣,我認爲data.frame是按列date排序的。

許多解決方案之一。可能棘手的一點是找到過渡期。這可以在rle的幫助下完成。

rle.df <- rle(df$state) 
# get indices of a-to-b transition -> 3,7 
idx <- cumsum(rle.df$lengths)[c(TRUE, FALSE)] 
# get indices of b-to-a transition -> 5,9 
idx2 <- cumsum(rle.df$lengths)[c(FALSE, TRUE)] 
# construct appropriate lengths -> 5,4 
idx2 <- c(idx2[1], diff(idx2)) 
# do a rep with idx2 fro times and df$date[idx] for value 
df$changedate <- unlist(lapply(1:length(idx2), function(vv) { 
    rep(df$date[idx[vv]], idx2[vv]) 
})) 

> df 
    id.  date. state changedate 
1 1 2012-01-01  a 2012-01-03 
2 1 2012-01-02  a 2012-01-03 
3 1 2012-01-03  a 2012-01-03 
4 1 2012-01-04  b 2012-01-03 
5 1 2012-01-05  b 2012-01-03 
6 2 2013-01-01  a 2013-01-02 
7 2 2013-01-02  a 2013-01-02 
8 2 2013-01-03  b 2013-01-02 
9 2 2013-01-04  b 2013-01-02 

使用data.table(我只注意到你也有.id.列,使我們可以拆分,並通過rle發現過渡指標申請之日起)的替代解決方案。

require(data.table) 
rle.df <- rle(df$state) 
idx <- cumsum(rle.df$lengths)[c(TRUE, FALSE)] 
idx2 <- cumsum(rle.df$lengths)[c(FALSE, TRUE)] 
idx <- c(idx[1], tail(idx, -1) - head(idx2, -1)) 

dt <- data.table(df, key="id.") 
out <- dt[, `:=`(changedate=date.[idx[id.]]), by=id.] 

> out 
    id.  date. state changedate 
1: 1 2012-01-01  a 2012-01-03 
2: 1 2012-01-02  a 2012-01-03 
3: 1 2012-01-03  a 2012-01-03 
4: 1 2012-01-04  b 2012-01-03 
5: 1 2012-01-05  b 2012-01-03 
6: 2 2013-01-01  a 2013-01-02 
7: 2 2013-01-02  a 2013-01-02 
8: 2 2013-01-03  b 2013-01-02 
9: 2 2013-01-04  b 2013-01-02 
+2

確保您的數據首先按日期排序,否則第一行會爲您提供與您期望的內容不同的內容。 –