いっぱい関数つくったりする前に、やっぱりapply系を使いこなしておきたい。
ということで、apply()の練習。
apply()は行列(matrix)の行(1)あるいは列(2)を対象として関数を適用する。
apply(X,MARGIN,FUN,OA)
X: 対象とする行列
MARGIN: 1 あるいは 2
FUN: 関数
OA: FUNに与える X 以外の引数(必要時のみ)
まず、適当な行列をつくる
set.seed(0) # 乱数のseedを規定
numbers <- rnorm(12,0,1)
matrix1 <- matrix(numbers,nrow=4)
> matrix1
[,1] [,2] [,3]
[1,] 1.2629543 0.4146414 -0.005767173
[2,] -0.3262334 -1.5399500 2.404653389
[3,] 1.3297993 -0.9285670 0.763593461
[4,] 1.2724293 -0.2947204 -0.799009249
行単位でmax()。
> apply(matrix1,1,max)
[1] 1.262954 2.404653 1.329799 1.272429
列単位でmax()。
> apply(matrix1,2,max)
[1] 1.3297993 0.4146414 2.4046534
自作関数をつくってみる。関数名はf1220.1()。
max()で求めたxの最大値にyを足す。
f1220.1 <- function(x,y){
z <- max(x) + y
return(z)
}
関数の動作確認。1, 2, 3の最大値に1を足すと4。
num123 <- c(1,2,3)
> f1220.1(num123,1)
[1] 4
apply()にはFUNのoptional argumentsを与えることができる。
行あるいは列単位でf1220.1()を実行。引数は1。
> apply(matrix1,1,f1220.1,1)
[1] 2.262954 3.404653 2.329799 2.272429
> apply(matrix1,2,f1220.1,1)
[1] 2.329799 1.414641 3.404653
引数は複数でもOK。
f1220.2 <- function(x,y,a,b){
z <- max(x) + y + a + b
return(z)
}
> apply(matrix1,1,f1220.2,1,1,1)
[1] 4.262954 5.404653 4.329799 4.272429
> apply(matrix1,2,f1220.2,1,1,1)
[1] 4.329799 3.414641 5.404653
apply()の対象となる行列に、行と列の名前がある場合。
colnames(matrix1) <- c("A","B","C")
rownames(matrix1) <- c("first.row","second.row","third.row","fourth.row")
> matrix1
A B C
first.row 1.2629543 0.4146414 -0.005767173
second.row -0.3262334 -1.5399500 2.404653389
third.row 1.3297993 -0.9285670 0.763593461
fourth.row 1.2724293 -0.2947204 -0.799009249
結果はこんな風になる。
> apply(matrix1,1,max)
first.row second.row third.row fourth.row
1.262954 2.404653 1.329799 1.272429
> apply(matrix1,2,max)
A B C
1.3297993 0.4146414 2.4046534
次に、lapplyとsapplyの練習。
まず、適当なリストをつくる。
set.seed(0)
a <- rnorm(10,0,1)
set.seed(1)
b <- rnorm(10,0,1)
list1 <- list(a,b)
> list1
[[1]]
[1] 1.262954285 -0.326233361 1.329799263 1.272429321
[5] 0.414641434 -1.539950042 -0.928567035 -0.294720447
[9] -0.005767173 2.404653389
[[2]]
[1] -0.6264538 0.1836433 -0.8356286 1.5952808 0.3295078
[6] -0.8204684 0.4874291 0.7383247 0.5757814 -0.3053884
lapplyはリストを対象とする。リストの各要素に対して関数を適用する。
> lapply(list1,mean)
[[1]]
[1] 0.358924
[[2]]
[1] 0.1322028
sapplyはlapplyの結果をsimplifyして返す。
> sapply(list1,mean)
[1] 0.3589240 0.1322028
自作関数も動く。
f1220.3 <- function(x){
y <- x + 1
return(y)
}
> lapply(list1,f1220.3)
[[1]]
[1] 2.26295428 0.67376664 2.32979926 2.27242932 1.41464143
[6] -0.53995004 0.07143297 0.70527955 0.99423283 3.40465339
[[2]]
[1] 0.3735462 1.1836433 0.1643714 2.5952808 1.3295078 0.1795316
[7] 1.4874291 1.7383247 1.5757814 0.6946116
> sapply(list1,f1220.3)
[,1] [,2]
[1,] 2.26295428 0.3735462
[2,] 0.67376664 1.1836433
[3,] 2.32979926 0.1643714
[4,] 2.27242932 2.5952808
[5,] 1.41464143 1.3295078
[6,] -0.53995004 0.1795316
[7,] 0.07143297 1.4874291
[8,] 0.70527955 1.7383247
[9,] 0.99423283 1.5757814
[10,] 3.40465339 0.6946116
引数を必要とする関数も動かせる。
f1220.4 <- function(x,b){
y <- x + b
return(y)
}
> lapply(list1,f1220.4,2)
[[1]]
[1] 3.262954 1.673767 3.329799 3.272429 2.414641 0.460050 1.071433
[8] 1.705280 1.994233 4.404653
[[2]]
[1] 1.373546 2.183643 1.164371 3.595281 2.329508 1.179532 2.487429
[8] 2.738325 2.575781 1.694612
> sapply(list1,f1220.4,2)
[,1] [,2]
[1,] 3.262954 1.373546
[2,] 1.673767 2.183643
[3,] 3.329799 1.164371
[4,] 3.272429 3.595281
[5,] 2.414641 2.329508
[6,] 0.460050 1.179532
[7,] 1.071433 2.487429
[8,] 1.705280 2.738325
[9,] 1.994233 2.575781
[10,] 4.404653 1.694612
リストの中のリストも対象にできる。
まず、入れ子状のリストをつくる。
names <- c("a","b","c","d","e")
set.seed(0)
value.a <- rnorm(10,0,1)
set.seed(1)
value.b <- rnorm(10,0,1)
set.seed(2)
value.c <- rnorm(10,0,1)
set.seed(3)
value.d <- rnorm(10,0,1)
set.seed(4)
value.e <- rnorm(10,0,1)
list2 <- list()
list2$names <- names
values <- list(a=value.a, b=value.b, c=value.c, d=value.d, e=value.e)
list2$values <- values
> list2
$names
[1] "a" "b" "c" "d" "e"
$values
$values$a
[1] 1.262954285 -0.326233361 1.329799263 1.272429321
[5] 0.414641434 -1.539950042 -0.928567035 -0.294720447
[9] -0.005767173 2.404653389
$values$b
[1] -0.6264538 0.1836433 -0.8356286 1.5952808 0.3295078
[6] -0.8204684 0.4874291 0.7383247 0.5757814 -0.3053884
$values$c
[1] -0.89691455 0.18484918 1.58784533 -1.13037567 -0.08025176
[6] 0.13242028 0.70795473 -0.23969802 1.98447394 -0.13878701
$values$d
[1] -0.96193342 -0.29252572 0.25878822 -1.15213189 0.19578283
[6] 0.03012394 0.08541773 1.11661021 -1.21885742 1.26736872
$values$e
[1] 0.2167549 -0.5424926 0.8911446 0.5959806 1.6356180
[6] 0.6892754 -1.2812466 -0.2131445 1.8965399 1.7768632
クラスを確認。
> class(list2)
[1] "list"
> class(list2$values)
[1] "list"
入れ子のリストにlapply()を適用。
> lapply(list2$values,mean)
$a
[1] 0.358924
$b
[1] 0.1322028
$c
[1] 0.2111516
$d
[1] -0.06713568
$e
[1] 0.5665293
sapply()も動く。
> sapply(list2$values,mean)
a b c d e
0.35892396 0.13220278 0.21115165 -0.06713568 0.56652929
リストの中の行列にはapply()が使える。
まず、行列を含むリストをつくる。
list3 <- list()
list3$names <- names
values <- cbind(a=value.a, b=value.b, c=value.c, d=value.d, e=value.e)
rownames(values) <- seq(1,10,1)
list3$values <- values
> list3
$names
[1] "a" "b" "c" "d" "e"
$values
a b c d e
1 1.262954285 -0.6264538 -0.89691455 -0.96193342 0.2167549
2 -0.326233361 0.1836433 0.18484918 -0.29252572 -0.5424926
3 1.329799263 -0.8356286 1.58784533 0.25878822 0.8911446
4 1.272429321 1.5952808 -1.13037567 -1.15213189 0.5959806
5 0.414641434 0.3295078 -0.08025176 0.19578283 1.6356180
6 -1.539950042 -0.8204684 0.13242028 0.03012394 0.6892754
7 -0.928567035 0.4874291 0.70795473 0.08541773 -1.2812466
8 -0.294720447 0.7383247 -0.23969802 1.11661021 -0.2131445
9 -0.005767173 0.5757814 1.98447394 -1.21885742 1.8965399
10 2.404653389 -0.3053884 -0.13878701 1.26736872 1.7768632
クラスを確認。
> class(list3)
[1] "list"
> class(list3$values)
[1] "matrix"
apply()を動かす。
> apply(list3$values,1,max)
1 2 3 4 5 6
1.2629543 0.1848492 1.5878453 1.5952808 1.6356180 0.6892754
7 8 9 10
0.7079547 1.1166102 1.9844739 2.4046534
> apply(list3$values,2,max)
a b c d e
2.404653 1.595281 1.984474 1.267369 1.896540
こういうのをちゃんと理解してから複雑な仕事をした方が良い。