-1

次のデータフレームがあります。

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でこれをエレガントに行う方法はありますか? 前もって感謝します。

4

1 に答える 1

2

編集:セバスチャンが言及しているように、 data.frame は column によって順序付けられていると想定していますdate

多くのソリューションの 1 つ。おそらく難しいのは、移行期間を見つけることです。これは、 の助けを借りて実現できます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
于 2013-01-17T23:21:09.670 に答える