Rのデバッグ

debug()

というデバッグ関数を勉強した。
 
今、連続した1の開始点を見つける関数findruns()を作ったとする。
とりあえず、テストデータで試してみると

# 誤りあり
findruns <- function(x,k) {
	n <- length(x)
	runs <- NULL
	for (i in 1:(n-k)) {
		if (all(x[i:i+k-1]==1)) runs <- c(runs,i)
	}
	return(runs)
}
findruns(c(1,0,0,1,1,0,1,1,1), 2)
[1] 4 7
#本当は4, 7, 8
# debug を始める
debug(findruns)
findruns(c(1,0,0,1,1,0,1,1,1), 2)
debugging in: findruns(c(1, 0, 0, 1, 1, 0, 1, 1, 1), 2)
 #1 の debug: {
    n <- length(x)
    runs <- NULL
    for (i in 1:(n - k)) {
        if (all(x[i:i + k - 1] == 1)) 
            runs <- c(runs, i)
    }
    return(runs)
}
Browse[2]>  # エンターで次に進む。
 #3 の debug: n <- length(x)
Browse[2]> n # nでも次に進む。この時点でprint(n)をしても実はnは定義されていない。次以降。
 #5 の debug: runs <- NULL
Browse[2]> 
 #7 の debug: for (i in 1:(n - k)) {
    if (all(x[i:i + k - 1] == 1)) #先に言ってしまうと間違いはここ。
        runs <- c(runs, i)
}
Browse[2]> print(n) # nのオブジェクトを表示するときは、print()を使用する。
[1] 9
Browse[2]> x # オブジェクトを入れると表示してくれる。
[1] 1 0 0 1 1 0 1 1 1
Browse[2]> Q #終了するときは大文字のQ。

undebug()していないとデバッグが終わらない。

undebug(findruns)

 
seqのところを()くくりにしたら解決、かと思いきやそうでもない。
おそらく、for loopのところに問題があるとにらんで、for loopの途中にデバッグを仕掛けるとき、

blowser()

を使う。

findruns <- function(x,k) {
	n <- length(x)
	runs <- NULL
	for (i in 1:(n-k)) {
		if (all(x[i:(i+k-1)]==1)) runs <- c(runs,i)
		if (i== n-k) browser()
	}
	return(runs)
}
findruns(c(1,0,0,1,1,0,1,1,1), 2)
Called from: findruns(c(1, 0, 0, 1, 1, 0, 1, 1, 1), 2)
Browse[1]> print(n)
[1] 9
Browse[1]> i # i を入力する。
[1] 7
Browse[1]> k # k を入力する。
[1] 2
Browse[1]> x # x を入力する。
[1] 1 0 0 1 1 0 1 1 1
Browse[1]> i:(i+k-1) # i:(i+k-1) を入力する。
[1] 7 8

for loopの最後まで来て、xの中身の7, 8番目の項までしか取れていないことがわかった。
ということでfor loopをもうひとつ付け足しておく。

findruns <- function(x,k) {
	n <- length(x)
	runs <- NULL
	for (i in 1:(n-k+1)) {                            # debug 2
		if (all(x[i:(i+k-1)]==1)) runs <- c(runs,i) # debug 1
	}
	return(runs)
}
findruns(c(1, 0, 0, 1, 1, 0, 1, 1, 1), 2)
[1] 4 7 8