3

特定のデータフレームについて、ブール値に基づいて分割し、その行とその時点までの前の行にラベルを適用したいと思います。

次のデータフレームを想定しています。

test <- data.frame(x = 1:10, y = c(F, F, F, T, F, F, T, F, F, F))

最終的には、データフレームの特定の部分のラベルを含む新しい列を作成したいと思います。理想的には、次のようなものです。

x   y   z
1   F   1
2   F   1
3   F   1
4   T   1
5   F   2
6   F   2
7   T   2
8   F   3
9   F   3
10  F   3

私の現在の考えは、次のような関数でデータフレームをループする必要があるということです(ただし正確ではありません)。

label.portion <- function(test) {
  for (i in 1:nrow(test)) {
    z <- 1
    if(test$y[i]) { z <- z + 1 }
    return(z)
  }
}

これを行うための最良/最も簡単な方法は何ですか?どんな助けでも大歓迎です。

4

4 に答える 4

4

あなたのzコラムは次のように構築することができます

z <- with(test, sum(y)-rev(cumsum(rev(y)))+1)

あなたの例のように、すべての新しいz値をaのFALSE y後に開始させるために。TRUE y

その後、あなたはcbind(test, z)あなたが望むものを手に入れるために行うことができます。

于 2013-03-26T02:27:14.980 に答える
4

を使用したワンライナーソリューションtransform

transform(test,z= cumsum(c(0,diff(y)) == -1)+1)

    x     y z
1   1 FALSE 1
2   2 FALSE 1
3   3 FALSE 1
4   4  TRUE 1
5   5 FALSE 2
6   6 FALSE 2
7   7  TRUE 2
8   8 FALSE 3
9   9 FALSE 3
10 10 FALSE 3
于 2013-03-26T02:41:35.733 に答える
3

他のソリューションよりもわずかに高速な別のワンライナーソリューション(を除くdata.table

test <- data.frame(x = 1:10, y = c(F, F, F, T, F, F, T, F, F, F))
test$z <- c(1, head(cumsum(test$y), -1) + 1)
test
##     x     y z
## 1   1 FALSE 1
## 2   2 FALSE 1
## 3   3 FALSE 1
## 4   4  TRUE 1
## 5   5 FALSE 2
## 6   6 FALSE 2
## 7   7  TRUE 2
## 8   8 FALSE 3
## 9   9 FALSE 3
## 10 10 FALSE 3

提供されている他のソリューションのベンチマーク(data.tableを除く)

test <- data.frame(x = 1:1e+05, y = sample(c(T, F), size = 1e+05, replace = TRUE))
microbenchmark(c(1, head(cumsum(test$y), -1) + 1), cumsum(c(0, diff(test$y)) == -1) + 1, with(test, sum(y) - rev(cumsum(rev(y))) + 
    1), times = 100)
## Unit: milliseconds
##                                          expr      min       lq   median       uq       max neval
##            c(1, head(cumsum(test$y), -1) + 1) 1.685473 1.758474 1.865409 4.647218  5.091512   100
##          cumsum(c(0, diff(test$y)) == -1) + 1 4.064867 4.379714 6.936561 7.338810  7.657961   100
##  with(test, sum(y) - rev(cumsum(rev(y))) + 1) 2.568766 2.720395 5.396096 5.701176 30.642436   100
于 2013-03-26T03:05:42.160 に答える
2

na.locfエレガンス(および効率)をコーディングするためにfromxtsおよびdata.tableを使用するアプローチを次に示します。

library(data.table)
library(xts) # for na.locf
test <- data.table(test)


test[(y), grp := seq_along(y)][, grp := na.locf(grp, fromLast = TRUE)]
test[is.na(grp), grp := max(test[, grp], na.rm =TRUE) + 1L]

そして、はるかに明確で高速なアプローチ

test[, grp := {xx <- diff(c(0,.I[y], length(.I))); rep.int(seq_along(xx),xx)}]

diffで実装されたforループを使用することに注意してくださいR。したがって、Rcpp砂糖の実装)はより高速になります(cpp関数はこれらのほとんどを水から吹き飛ばすと確信しています)

于 2013-03-26T02:45:18.907 に答える