0

一意の ID ごとに複数のエントリを持つ data.frame があります。定義済みの制限時間である 60 秒を超えている行を特定する必要があります。時間列を分割する必要がある行を示すために、「toolong」という用語が入力された列を既に添付しています。次に、「toolong」を持つ行のすぐ下に新しい行を作成し、アクション列を「l」に変更し、時間列を前回の時間 - 60 に変更することを除いて、「親行」と同じ情報をすべて保持します。親行には、アクション列が「for」に変更され、時間が 60 秒に変更されることを除いて、すべて同じ情報が含まれます。元のデータベースには合計 32 列あるため、アクションと時間以外のすべての行の内容を保持する必要があります。

例:

id <- c(1,1,1,1,2,2,2,2)
resting <- c("f","f","toolong","f","f","f","toolong","f")
action <- c("h","h","l","d","h","h","l","d")
time <- c(90,12,120,14,90,12,110,14)
other <- c(1,2,3,4,5,6,5,4)
dat <- data.frame(cbind(id,resting,action,time,other))

どのように見せたいですか:

   id2 resting2 action2 time2 other2
1    1        f       h    90      1
2    1        f       h    12      2
3    1  toolong     for    60      3
4    1  toolong       l    60      3
5    1        f       d    14      4
6    2        f       h    90      5
7    1        f       h    12      6
8    2  toolong     for    60      5
9    2  toolong       l    50      5
10   2        f       d    14      4

ありがとう、ティム

4

2 に答える 2

2

まず、長すぎる行を繰り返します...

R>rowID <- rep(1:8, times=as.factor(resting))        
R>dat2 <- dat[rowID,]
R>dat2
    id resting action time other
1    1       f      h   90     1
2    1       f      h   12     2
3    1 toolong      l  120     3
3.1  1 toolong      l  120     3
4    1       f      d   14     4
5    2       f      h   90     5
6    2       f      h   12     6
7    2 toolong      l  110     5
7.1  2 toolong      l  110     5
8    2       f      d   14     4

次に、重複したものについては、前のレコードごとに 60 分を減算します...

R>dups <- unlist(tapply(duplicated(rowID), rowID,cumsum))
R>dat2$time <- dat2$time - 60*dups
R>dat2[dat2$resting == "toolong", "time"] <- pmin(60, dat2[dat2$resting == "toolong",     "time"] )
R>dat2
    id resting action time other
1    1       f      h   90     1
2    1       f      h   12     2
3    1 toolong      l   60     3
3.1  1 toolong      l   60     3
4    1       f      d   14     4
5    2       f      h   90     5
6    2       f      h   12     6
7    2 toolong      l   60     5
7.1  2 toolong      l   50     5
8    2       f      d   14     4
于 2013-10-17T20:04:53.530 に答える
1
dat2 <- rbind(dat, dat[ dat$resting=="toolong" , ])
dat2 <- dat2[order(rownames(dat2)), ]
dat2[duplicated(dat2), "action"] <- "l"
names(dat2) <- paste0(names(dat2), "2")
dat2
#-------
   id2 resting2 action2 time2 other2
1    1        f       h    90      1
2    1        f       h    12      2
3    1  toolong       l   120      3
31   1  toolong       l   120      3
4    1        f       d    14      4
5    2        f       h    90      5
6    2        f       h    12      6
7    2  toolong       l   110      5
71   2  toolong       l   110      5
8    2        f       d    14      4

選択ベクトルとして使用される重複行名を作成するもう 1 つの方法はmapply、論理ベクトルに 1 を追加することでした。行名のピリオドはより良い「だまされた」指標であるため、これにはいくつかの利点があります。

 dat[ unlist(mapply( rep, rownames(dat), 1+(dat$resting=="toolong"))) , ]

    id resting action time other
1    1       f      h   90     1
2    1       f      h   12     2
3    1 toolong      l  120     3
3.1  1 toolong      l  120     3
4    1       f      d   14     4
5    2       f      h   90     5
6    2       f      h   12     6
7    2 toolong      l  110     5
7.1  2 toolong      l  110     5
8    2       f      d   14     4

質問のコメント::変更への対処:

dat2$action2 <- as.character(dat2$action2)
dat2[ dat2$resting2=="toolong" & !duplicated(dat2) , "action2"] <- "for"
dat2
   id2 resting2 action2 time2 other2
1    1        f       h    90      1
2    1        f       h    12      2
3    1  toolong     for   120      3
31   1  toolong       l   120      3
4    1        f       d    14      4
5    2        f       h    90      5
6    2        f       h    12      6
7    2  toolong     for   110      5
71   2  toolong       l   110      5
8    2        f       d    14      4
于 2013-10-17T19:46:35.380 に答える