12

私は非常に大きなdata.frame(実際にはdata.table)を持っています。さて、物事を簡単にするために、私の data.frame が次のようであると仮定しましょう:

x <- c(1, 1, 0, 0, 1, 0, 0, NA, NA, 0) 
y <- c(1 ,0 ,NA, NA, 0, 0, 0, 1, 1, 0)
mydf <- data.frame(rbind(x,y))

NAを考慮せずに、最後のシーケンスが3つの連続したゼロで形成されている行(ある場合)を特定したいと思います。したがって、上記の例では、最初の行の最後のシーケンスに 3 つの連続するゼロがありますが、2 番目の行にはありません。

ベクトル(data.frameではない)がある場合にのみ、その方法を知っています:

runs <-  rle(x[is.na(x)==F])

runs$lengths[length(runs$lengths)] > 2 & runs$values[length(runs$lengths)]==0

私は明らかにループを行うことができ、私が望むものを手に入れることができます。しかし、それは信じられないほど非効率的で、実際の data.frame はかなり大きいです。それで、最速の方法で行う方法についてのアイデアはありますか?

apply は便利だと思いますが、今のところ使用することは考えられません。また、おそらくこれを行う data.table 方法がありますか?

ps .: 実は、この data.frame は、元の data.table の形状を変更したものです。元の形式の data.frame でどうにかして仕事をすることができれば、それは問題ありません。私のdata.frameが元々どのようになっているかを確認するには、次のように考えてください。

x <- c(1, 1, 0, 0, 1, 0, 0, 0) 
y <- c(1 ,0 , 0, 0, 0, 1, 1, 0)

myOriginalDf <- data.frame(value=c(x,y), id=rep(c('x','y'), c(length(x), length(y))))
4

4 に答える 4

20

を使用しdata.tableて、あなたの質問があなたが実際にやりたいことを示唆しているように、私が見る限り、これはあなたが望むことをしています

DT <- data.table(myOriginalDf)

# add the original order, so you can't lose it
DT[, orig := .I]

# rle by id, saving the length as a new variables

DT[, rleLength := {rr <- rle(value); rep(rr$length, rr$length)}, by = 'id']

# key by value and length to subset 

setkey(DT, value, rleLength)

# which rows are value = 0 and length > 2

DT[list(0, unique(rleLength[rleLength>2])),nomatch=0]

##    value rleLength id orig
## 1:     0         3  x    6
## 2:     0         3  x    7
## 3:     0         3  x    8
## 4:     0         4  y   10
## 5:     0         4  y   11
## 6:     0         4  y   12
## 7:     0         4  y   13
于 2013-03-01T05:26:53.127 に答える
8

これは、ベクトルのソリューションに基づくapplyステートメントです。それはあなたが望むことをするかもしれません。

z <- apply(mydf,1, function(x) {
runs <-  rle(x[is.na(x)==FALSE]) ;
runs$lengths[length(runs$lengths)] > 2 & runs$values[length(runs$lengths)]==0 })

mydf[z,]

#   X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
# x  1  1  0  0  1  0  0 NA NA   0
于 2013-03-01T05:33:00.120 に答える
6

isMidPoint真ん中0がある場合は、以下で識別します。

library(data.table)
myOriginalDf <- data.table(myOriginalDf, key="id")

myOriginalDf[, isMidPoint := FALSE]
myOriginalDf <- myOriginalDf[!is.na(value)][(c(FALSE, !value[-(1:2)], FALSE) & c(!value[-(length(value))], FALSE) & c(FALSE, !value[-length(value)])), isMidPoint := TRUE, by=id]

説明:

連続した3つの要素を見つけるには、2番目から最後から2番目までの各要素を、その前後の隣接要素と比較するだけです。

値は0 / 1であるため、効果的T / Fになります。これにより、評価が非常に簡単になります(NAがなかったと仮定)。

vが値(NAなし)の場合、要素とその後続要素が0の場合!v & !v[-1]はすべてTRUEになります。加算する& !v[-(1:2)]と、一連の3の中間にある場合は常にこれが当てはまります0sこれも一連の4+0sをキャッチすることに注意してください!

次に、残っているのは、(1)NAを削除(および考慮)しながら上記を計算し、(2)id値で分離することだけです。幸いなことに、data.tableこれらは簡単です。

結果:

  > myOriginalDf

    row value id isMidPoint
 1:   1     1  x      FALSE
 2:   2     1  x      FALSE
 3:   3     0  x      FALSE
 4:   4     0  x      FALSE
 5:   5     1  x      FALSE
 6:   6     0  x      FALSE
 7:   7     0  x       TRUE  <~~~~
 8:   9     0  x      FALSE
 9:  10     1  x      FALSE
10:  11     0  x      FALSE
11:  12     0  x       TRUE  <~~~~
12:  13     0  x       TRUE  <~~~~
13:  14     0  x       TRUE  <~~~~
14:  15     0  x      FALSE
15:  16     1  y      FALSE
16:  17     0  y      FALSE
17:  18     0  y       TRUE  <~~~~
18:  20     0  y      FALSE
19:  21     1  y      FALSE
20:  22     1  y      FALSE
21:  23     0  y      FALSE
22:  25     0  y       TRUE  <~~~~
23:  27     0  y       TRUE  <~~~~
24:  29     0  y      FALSE
    row value id isMidPoint

コメントごとに編集:

の最後のシーケンスを見つけたい場合は、次を使用します。

    max(which(myOriginalDf$isMidpoint))

最後のシーケンスが真であるかどうかを知りたい場合は、次を使用します。

  # Will be TRUE if last possible sequence is 0-0-0
  #   Note, this accounts for NA's as well
  myOriginalDf[!is.na(value), isMidpoint[length(isMidpoint)-1]
于 2013-03-01T05:45:12.167 に答える