プログラミングテクニック vs. プログラミング作法
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
//青木繁伸
うまいプログラミングと確実なプログラミングは相反する部分...
実際に,色々なライブラリに書かれているプログラムから例題...
ちなみに,私自身は,COLOR(RED){トリッキーなプログラムや,...
----
#contents
----
*if - else if - else など
concord ライブラリの coincidence.matrix 関数より
if (any(is.na(x)))
mc <- apply(x, 2, vn) - 1
else mc <- rep(1, dimx[2])
何のコメントも必要ないものであるが,
if (any(is.na(x))) {
mc <- apply(x, 2, vn) - 1
}
else {
mc <- rep(1, dimx[2])
}
と書くことを勧める(このプログラムをコンソールから入力し...
if や else に対応する処理が一つの文で済んでいるうちはいい...
if (any(is.na(x)))
mc <- apply(x, 2, vn) - 1
追加処理
else mc <- rep(1, dimx[2])
などと付け加えてしまうと,変なことになってしまう。~
前もって { } を補っておけば,いくら付け加えても OK。転ば...
なお,R の特性を生かして書くなら,
mc <- if (any(is.na(x))) apply(x, 2, vn) - 1 else rep...
とも書ける。しかし,こんな書き方をしても,何のメリットが...
stats の PP.test には,
if (lshort)
l <- trunc(4 * (n/100)^0.25)
else l <- trunc(12 * (n/100)^0.25)
という部分があるが,
l <- 4 * (n/100)^0.25)
if (lshort == FALSE) {
l <- 3 * l
}
l <- trunc(l)
の方が,なんぼかわかりやすい。
l <- trunc(ifelse(lshort, 4, 12) * (n/100)^0.25)
とするかどうかは,議論の分かれるところかもしれない。
*R 特有のリサイクルという機能
同じく concord ライブラリの coincidence.matrix 関数より
cm <- matrix(rep(0, nval * nval), nrow = nval) # (1)
これが,
cm <- matrix(0, nrow = nval, ncol = nval) # (2)
や
cm <- matrix(rep(0, nval * nval), nrow = nval, ncol =...
と同じであることは,R の入門書の最初の方に書いてある。~
R 的には (2) なのだろうが(cm <- matrix(0, nval, nval) な...
しかし,こんなことを何百万回もやるのでなければ,どれでも...
一方,リサイクルはうまく使った方がわかりやすいこともある。~
stats の cancor には,平均偏差データを作る部分に以下のよ...
xcenter <- colMeans(x) # 列方向の平均値
x <- x - rep(xcenter, rep.int(nr, ncx)) # nr, ncx は ...
二行目は,
x <- scale(x, scale=FALSE)
と書くことができるが,平均値を求め直すのを嫌ったのかもし...
リサイクル機能を使うなら,
x <- t(t(x)-xcenter)
でよいが,やはり,これは技巧を凝らしすぎていることになる...
しかし,
x <- x - rep(xcenter, rep.int(nr, ncx))
のように rep 関数を二回も使う必要はなくて,
x <- x - rep(xcenter, each=nr)
とすることで,同じ結果になることも覚えておいて損はない(...
*条件のチェック
R では stopifnot という関数が用意されている。条件を満たさ...
base の prop.test でも,
if (any(n <= 0))
stop("Elements of n must be positive")
というのが最初の方にあるが,stopifnot を使うとすれば
stopifnot (all(n > 0))
ということで,もし条件が満たされないと,
Error: all(n > 0) is not TRUE
というエラーメッセージが返される。プログラムとしてはもう...
また,stopif ではなくて stopifnot と,わざざざ not を付け...
stopif (any(n) <= 0)
の方がわかりやすくはないのだろうか。~
「条件を満たさなければ停止」というのと,「この条件ならば...
*論理式の真偽
その stopifnot の中に,
for (i in 1:n) if (!(is.logical(r <- eval(ll[[i]])) &...
stop(paste(deparse(mc[[i + 1]]), "is not TRUE"), ...
というのがある。~
R に限らず,多くのプログラミング言語では,0のみが偽,0以...
ちなみに上のコードは,そのようにしただけではまだまだわか...
わかりやすく書くと,効率が悪くなるのだろうか。そんなこと...
*本に書かれている式をそのまま書く必要はない
stats に含まれる Box.test に
STATISTIC <- n * (n + 2) * sum(1/seq(n - 1, n - lag) ...
と言う部分があるが,
STATISTIC <- n * (n + 2) * sum(obs^2 / seq(n - 1, n -...
の方が好ましい。(1) を sum(1/(seq(n - 1, n - lag) * obs^2...
ちょっとしたことが積み重なればプログラムはだんだんわかり...
*関数のパラメータを活用する
おなじく stats の Box.test に,
PVAL <- 1 - pchisq(STATISTIC, lag) # (1)
という部分があるが,
PVAL <- pchisq(STATISTIC, lag, lower=FALSE) # (2)
の方がよい。もし,(1)式の右辺に何か操作を加えるとき,かっ...
*中間変数を使わない
式の計算の途中で,代入しない。
stats の PP.test に
table <- cbind(c(4.38, 4.15, 4.04, 3.99, 3.98, 3.96),...
3.8, 3.73, 3.69, 3.68, 3.66), c(3.6, 3.5, 3.45, 3...
3.42, 3.41), c(3.24, 3.18, 3.15, 3.13, 3.13, 3.12...
1.19, 1.22, 1.23, 1.24, 1.25), c(0.8, 0.87, 0.9, ...
0.93, 0.94), c(0.5, 0.58, 0.62, 0.64, 0.65, 0.66)...
0.24, 0.28, 0.31, 0.32, 0.33))
table <- -table
がある。
table <- -cbind(c(4.38, 4.15, 中略, 0.33))
でよい。
*わかりやすい関数を使う
stats の PP.test に
tablen <- dim(table)[2]
というのがある。この table(前項参照) は二次元配列なので,
tablen <- ncol(table)
の方が,わかりやすい。
ちなみに,NCOL という関数もあるが,
> NCOL
function (x)
if (is.array(x) && length(dim(x)) > 1 || is.data.frame(x...
<environment: namespace:base>
> ncol
function (x)
dim(x)[2]
<environment: namespace:base>
であり,ncol は,単に dim(x)[2] に過ぎないこともわかる。
> x <- 1:3
> NCOL(x)
[1] 1
> ncol(x)
NULL
のいずれが好ましいか。私は ncol を使いたいと思う。
stats の cmdscale 関数に
x[row(x) > col(x)] <- d^2 # x は正方行列
という部分がある。パズルのようだが,何のことはなくて,
x[lower.tri(x)] <- d^2
のことである。どっちも,関数を知らないことにはわかりにく...
> lower.tri
function (x, diag = FALSE)
{
x <- as.matrix(x)
if (diag)
row(x) >= col(x)
else row(x) > col(x)
}
ではあるのだが。
*for の効用と乱用と使用自粛
ライブラリに納められている関数を見ると,for は実に良く使...
stats の PP.test の中(前項に引き続く部分)に,次のような...
tableipl <- numeric(tablen)
for (i in (1:tablen)) tableipl[i] <- approx(tableT, t...
i], n, rule = 2)$y
sapply を使って
tableipl <- sapply(1:tablen, function(i) approx(table...
ということになる。
なぜ,for がよく使われるかというと,for が支配する文(処...
len <- length(tmp)
for (k in seq(from = 1, to = n.row.vars)) {
i <- seq(from = 1, to = len, by = len/n[k])
row.vars[[k]] <- unique(tmp[i])
tmp <- tmp[seq(from = 2, to = len/n[k])]
len <- length(tmp)
}
というような部分を,sapply() を使って書いても,簡単にも何...
for を消去できるのは,for が支配できる文が簡単なものであ...
つまり,
result <- 0
for (i in 1: n) {
result <- result+x[i]
}
みたいなものなら,
result <- sum(x)
でよい,とかいうレベルに過ぎないのである。
sum などという便利な関数がないなら(計算過程が複雑ならば...
終了行:
//青木繁伸
うまいプログラミングと確実なプログラミングは相反する部分...
実際に,色々なライブラリに書かれているプログラムから例題...
ちなみに,私自身は,COLOR(RED){トリッキーなプログラムや,...
----
#contents
----
*if - else if - else など
concord ライブラリの coincidence.matrix 関数より
if (any(is.na(x)))
mc <- apply(x, 2, vn) - 1
else mc <- rep(1, dimx[2])
何のコメントも必要ないものであるが,
if (any(is.na(x))) {
mc <- apply(x, 2, vn) - 1
}
else {
mc <- rep(1, dimx[2])
}
と書くことを勧める(このプログラムをコンソールから入力し...
if や else に対応する処理が一つの文で済んでいるうちはいい...
if (any(is.na(x)))
mc <- apply(x, 2, vn) - 1
追加処理
else mc <- rep(1, dimx[2])
などと付け加えてしまうと,変なことになってしまう。~
前もって { } を補っておけば,いくら付け加えても OK。転ば...
なお,R の特性を生かして書くなら,
mc <- if (any(is.na(x))) apply(x, 2, vn) - 1 else rep...
とも書ける。しかし,こんな書き方をしても,何のメリットが...
stats の PP.test には,
if (lshort)
l <- trunc(4 * (n/100)^0.25)
else l <- trunc(12 * (n/100)^0.25)
という部分があるが,
l <- 4 * (n/100)^0.25)
if (lshort == FALSE) {
l <- 3 * l
}
l <- trunc(l)
の方が,なんぼかわかりやすい。
l <- trunc(ifelse(lshort, 4, 12) * (n/100)^0.25)
とするかどうかは,議論の分かれるところかもしれない。
*R 特有のリサイクルという機能
同じく concord ライブラリの coincidence.matrix 関数より
cm <- matrix(rep(0, nval * nval), nrow = nval) # (1)
これが,
cm <- matrix(0, nrow = nval, ncol = nval) # (2)
や
cm <- matrix(rep(0, nval * nval), nrow = nval, ncol =...
と同じであることは,R の入門書の最初の方に書いてある。~
R 的には (2) なのだろうが(cm <- matrix(0, nval, nval) な...
しかし,こんなことを何百万回もやるのでなければ,どれでも...
一方,リサイクルはうまく使った方がわかりやすいこともある。~
stats の cancor には,平均偏差データを作る部分に以下のよ...
xcenter <- colMeans(x) # 列方向の平均値
x <- x - rep(xcenter, rep.int(nr, ncx)) # nr, ncx は ...
二行目は,
x <- scale(x, scale=FALSE)
と書くことができるが,平均値を求め直すのを嫌ったのかもし...
リサイクル機能を使うなら,
x <- t(t(x)-xcenter)
でよいが,やはり,これは技巧を凝らしすぎていることになる...
しかし,
x <- x - rep(xcenter, rep.int(nr, ncx))
のように rep 関数を二回も使う必要はなくて,
x <- x - rep(xcenter, each=nr)
とすることで,同じ結果になることも覚えておいて損はない(...
*条件のチェック
R では stopifnot という関数が用意されている。条件を満たさ...
base の prop.test でも,
if (any(n <= 0))
stop("Elements of n must be positive")
というのが最初の方にあるが,stopifnot を使うとすれば
stopifnot (all(n > 0))
ということで,もし条件が満たされないと,
Error: all(n > 0) is not TRUE
というエラーメッセージが返される。プログラムとしてはもう...
また,stopif ではなくて stopifnot と,わざざざ not を付け...
stopif (any(n) <= 0)
の方がわかりやすくはないのだろうか。~
「条件を満たさなければ停止」というのと,「この条件ならば...
*論理式の真偽
その stopifnot の中に,
for (i in 1:n) if (!(is.logical(r <- eval(ll[[i]])) &...
stop(paste(deparse(mc[[i + 1]]), "is not TRUE"), ...
というのがある。~
R に限らず,多くのプログラミング言語では,0のみが偽,0以...
ちなみに上のコードは,そのようにしただけではまだまだわか...
わかりやすく書くと,効率が悪くなるのだろうか。そんなこと...
*本に書かれている式をそのまま書く必要はない
stats に含まれる Box.test に
STATISTIC <- n * (n + 2) * sum(1/seq(n - 1, n - lag) ...
と言う部分があるが,
STATISTIC <- n * (n + 2) * sum(obs^2 / seq(n - 1, n -...
の方が好ましい。(1) を sum(1/(seq(n - 1, n - lag) * obs^2...
ちょっとしたことが積み重なればプログラムはだんだんわかり...
*関数のパラメータを活用する
おなじく stats の Box.test に,
PVAL <- 1 - pchisq(STATISTIC, lag) # (1)
という部分があるが,
PVAL <- pchisq(STATISTIC, lag, lower=FALSE) # (2)
の方がよい。もし,(1)式の右辺に何か操作を加えるとき,かっ...
*中間変数を使わない
式の計算の途中で,代入しない。
stats の PP.test に
table <- cbind(c(4.38, 4.15, 4.04, 3.99, 3.98, 3.96),...
3.8, 3.73, 3.69, 3.68, 3.66), c(3.6, 3.5, 3.45, 3...
3.42, 3.41), c(3.24, 3.18, 3.15, 3.13, 3.13, 3.12...
1.19, 1.22, 1.23, 1.24, 1.25), c(0.8, 0.87, 0.9, ...
0.93, 0.94), c(0.5, 0.58, 0.62, 0.64, 0.65, 0.66)...
0.24, 0.28, 0.31, 0.32, 0.33))
table <- -table
がある。
table <- -cbind(c(4.38, 4.15, 中略, 0.33))
でよい。
*わかりやすい関数を使う
stats の PP.test に
tablen <- dim(table)[2]
というのがある。この table(前項参照) は二次元配列なので,
tablen <- ncol(table)
の方が,わかりやすい。
ちなみに,NCOL という関数もあるが,
> NCOL
function (x)
if (is.array(x) && length(dim(x)) > 1 || is.data.frame(x...
<environment: namespace:base>
> ncol
function (x)
dim(x)[2]
<environment: namespace:base>
であり,ncol は,単に dim(x)[2] に過ぎないこともわかる。
> x <- 1:3
> NCOL(x)
[1] 1
> ncol(x)
NULL
のいずれが好ましいか。私は ncol を使いたいと思う。
stats の cmdscale 関数に
x[row(x) > col(x)] <- d^2 # x は正方行列
という部分がある。パズルのようだが,何のことはなくて,
x[lower.tri(x)] <- d^2
のことである。どっちも,関数を知らないことにはわかりにく...
> lower.tri
function (x, diag = FALSE)
{
x <- as.matrix(x)
if (diag)
row(x) >= col(x)
else row(x) > col(x)
}
ではあるのだが。
*for の効用と乱用と使用自粛
ライブラリに納められている関数を見ると,for は実に良く使...
stats の PP.test の中(前項に引き続く部分)に,次のような...
tableipl <- numeric(tablen)
for (i in (1:tablen)) tableipl[i] <- approx(tableT, t...
i], n, rule = 2)$y
sapply を使って
tableipl <- sapply(1:tablen, function(i) approx(table...
ということになる。
なぜ,for がよく使われるかというと,for が支配する文(処...
len <- length(tmp)
for (k in seq(from = 1, to = n.row.vars)) {
i <- seq(from = 1, to = len, by = len/n[k])
row.vars[[k]] <- unique(tmp[i])
tmp <- tmp[seq(from = 2, to = len/n[k])]
len <- length(tmp)
}
というような部分を,sapply() を使って書いても,簡単にも何...
for を消去できるのは,for が支配できる文が簡単なものであ...
つまり,
result <- 0
for (i in 1: n) {
result <- result+x[i]
}
みたいなものなら,
result <- sum(x)
でよい,とかいうレベルに過ぎないのである。
sum などという便利な関数がないなら(計算過程が複雑ならば...
ページ名: