計測結果を処理する為に、次のようなベクトルの中の、0が1~4回連続する部分を1に置き換える必要が出てきました。
c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0)
↓
c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0)
この方法、簡単そうに見えるのですが、なかなかできずに四苦八苦しました。
結局、下記の書き込みを参照してようやく解決出来ました。
https://tagsqa.com/detail/29800
rleという関数を使うのですが、最初に書いたベクトルを代入してみます。
rle(c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0))
Run Length Encoding
lengths: int [1:8] 2 6 6 4 6 2 1 6
values : num [1:8] 1 0 1 0 1 0 1 0
少しとっつきにくいのですが、このように、長さと値が返ってきます。
さらに
inverse.rle
という逆変換をしてくれる機能が素晴らしく使えます。
例えば下記のようになります。
value <- c(1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0)
r <- rle(value)
# 代入します
r$values[1] <- 9
# 値を見てみます
r$lengths
[1] 2 6 6 4 6 2 1 6
r$values
[1] 9 0 1 0 1 0 1 0
inverse.rle(r)
[1] 9 9 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0
このように、最初のデータフレームの2連続の1を9に置き換えた答えが返ってきます。
そこで冒頭の問題を解決する関数を作ってみました。
paste_0to1 <- function (data) {
r <- rle(data)
rev <- abs(r$values - 1)
len <- rev * r$lengths
flag <- which((len < 5) & (len != 0))
r$values[flag] <- 1
return(inverse.rle(r))
}
皆様の参考になれば幸いです。