次のような文字列で連続する 1 の最大数を取得する簡単な方法はあります
"000010011100011111001111111100"
か?
私は間違いなくループでそれを行うことができますが、実際のデータセットには約 500,000 レコードがあるため、それは避けたいと思います。
事前にご協力いただきありがとうございます。
次のような文字列で連続する 1 の最大数を取得する簡単な方法はあります
"000010011100011111001111111100"
か?
私は間違いなくループでそれを行うことができますが、実際のデータセットには約 500,000 レコードがあるため、それは避けたいと思います。
事前にご協力いただきありがとうございます。
を使用するrle
と、正規表現を使用するよりも時間がかかり、少しぎこちなくなります。Thomas' answerでは、値が 1 に等しい場合でも最大長を抽出する必要があります。
# make some data
set.seed(21)
N <- 1e5
s <- sample(c("0","1"), N*30, TRUE)
s <- split(s, rep(1:N, each=30))
s <- sapply(s, paste, collapse="")
# Thomas' (complete) answer
r <- function(S) {
sapply(S, function(x) {
rl <- rle(as.numeric(strsplit(x,"")[[1]]))
max(rl$lengths[rl$values==1])
})
}
# using regular expressions
g <- function(S) sapply(gregexpr("1*",S),
function(x) max(attr(x,'match.length')))
# timing
system.time(R <- r(s))
# user system elapsed
# 6.41 0.00 6.41
system.time(G <- g(s))
# user system elapsed
# 1.47 0.00 1.46
all.equal(R,G)
# [1] "names for target but not for current"
を使用せずにはるかに高速な代替方法は、次のように連続した 0 で分割することです。rle
# following thelatemail's comment, changed '0+' to '[^1]+'
strsplit(x, "[^1]+", perl=TRUE)
次に、ループして、リストの各要素の最大文字数を取得できます。これもrle
ソリューションよりも高速です。gregexpr
また、@ Joshuaのソリューションよりも高速です。いくつかのベンチマーク...
zz <- function(x) {
vapply(strsplit(x, "[^1]+", perl=TRUE), function(x) max(nchar(x)), 0L)
}
perl=TRUE
を追加して使用することで、@ Joshuaの関数も微調整できることに気付きましたvapply
。というわけでこちらも比較。
g2 <- function(S) vapply(gregexpr("1*",S, perl=TRUE),
function(x) max(attr(x,'match.length')), 0L)
require(microbenchmark)
microbenchmark(t1 <- zz(unname(s)), t2 <- g(unname(s)), t3 <- g2(unname(s)), times=50)
Unit: seconds
expr min lq median uq max neval
t1 <- zz(unname(s)) 1.187197 1.285065 1.344371 1.497564 1.565481 50
t2 <- g(unname(s)) 2.154038 2.307953 2.357789 2.417259 2.596787 50
t3 <- g2(unname(s)) 1.562661 1.854143 1.914597 1.954795 2.203543 50
identical(t1, t2) # [1] TRUE
identical(t1, t3) # [1] TRUE
使用rle
:
x <- "000010011100011111001111111100"
rr <- rle(strsplit(x,"")[[1]])
Run Length Encoding
lengths: int [1:9] 4 1 2 3 3 5 2 8 2
values : chr [1:9] "0" "1" "0" "1" "0" "1" "0" "1" "0"
追記:as.numeric
必要ないので外しました。ここから、連続する 1 の最大数を次のように取得できます。
max(rr$lengths[which(rr$values == "1")])
# [1] 8