こんにちは、usagi-sanです。
今回は自作関数の紹介をします。
ベクトルやデータフレームを簡単に縦、横方向に結合できる関数を作ってみました。
R言語でベクトルやデータフレームを結合させる際、データフレームのnamesが異なるときはerrorが出てしまいrbindが使えないなどの問題があります。
rbindやcbindを用いたことがある方は一度は、colnamesを合わせたり行数列数を合わせたりするなどしたことがあると思います。
今回紹介する関数は、namesや行数列数の調整を自動的に行ってくれます。
いちいち、colnamesやデータフレームの形を変更することなく、ベクトルやデータフレームの結合ができます。
関数の紹介
mergeRowAndColnamesWithData
関数mergeRowAndColnamesWithDataは、データフレームの行名と列名をデータフレームの要素に結合させる関数です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | mergeRowAndColnamesWithData <- function(x) { dataFrame <- as.data.frame(x) colnames(dataFrame) <- rep("", ncol(dataFrame)) rownames(dataFrame) <- seq_len(nrow(dataFrame)) for (i in seq_len(ncol(dataFrame))) { if (is.factor(dataFrame[, i])) { dataFrame[, i] <- as.character(dataFrame[, i]) } } if (!is.null(rownames(x))) { rownamesDataFrame <- as.data.frame(rownames(x)) colnames(rownamesDataFrame) <- rep("", ncol(rownamesDataFrame)) dataFrame <- cbind(rownamesDataFrame, dataFrame) } colnames(dataFrame) <- rep("", ncol(dataFrame)) if (!is.null(colnames(x))) { colnamesDataFrame <- as.data.frame(t(colnames(x))) if (ncol(x) != ncol(dataFrame)) { colnamesDataFrame <- cbind("", colnamesDataFrame) } colnames(colnamesDataFrame) <- rep("", ncol(colnamesDataFrame)) dataFrame <- rbind(colnamesDataFrame, dataFrame) } return(dataFrame) } |
ポイント
例えば、write.tableの引数にrow.names = FALSEやcol.names = FALSEを指定する場合、データフレームの行名と列名が出力に反映されなくなり、不都合が生じる場合があります。この関数を用いることで、rbindやcbindなどのデータフレームを結合させる関数を使うことなく、瞬時に行名と列名をデータフレームの要素に組み込むことができます。
mergeRowAndColnamesWithDataの引数を以下に示します。
x | データフレーム型のオブジェクト |
rowBind
関数rowBindは2つの(ベクトル型かデータフレーム型)のオブジェクトを縦方向に結合させる関数です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | rowBind <- function(x, y, rowNames = TRUE, colNames = TRUE, sep = TRUE) { dataFrameX <- mergeRowAndColnamesWithData(x) dataFrameY <- mergeRowAndColnamesWithData(y) if (!rowNames) { dataFrameX <- as.data.frame(dataFrameX[-1, ]) rownames(dataFrameX) <- seq_len(nrow(dataFrameX)) dataFrameY <- as.data.frame(dataFrameY[-1, ]) rownames(dataFrameY) <- seq_len(nrow(dataFrameY)) } if (!colNames) { dataFrameX <- as.data.frame(dataFrameX[, -1]) colnames(dataFrameX) <- rep("", ncol(dataFrameX)) dataFrameY <- as.data.frame(dataFrameY[, -1]) colnames(dataFrameY) <- rep("", ncol(dataFrameY)) } diffOfNCol <- ncol(dataFrameX) - ncol(dataFrameY) if (diffOfNCol > 0) { dataFrameY <- cbind(dataFrameY, matrix(rep("", nrow(dataFrameY) * abs(diffOfNCol)), nrow = nrow(dataFrameY))) } else { dataFrameX <- cbind(dataFrameX, matrix(rep("", nrow(dataFrameX) * abs(diffOfNCol)), nrow = nrow(dataFrameX))) } colnames(dataFrameX) <- rep("", ncol(dataFrameX)) colnames(dataFrameY) <- rep("", ncol(dataFrameY)) bindedDataFrame <- NULL if (sep) { bindedDataFrame <- rbind(dataFrameX, rep("", ncol(dataFrameX)), dataFrameY) } else { bindedDataFrame <- rbind(dataFrameX, dataFrameY) } colnames(bindedDataFrame) <- rep("", ncol(bindedDataFrame)) return(bindedDataFrame) } |
ポイント
rbindとの違いは、列名や列数を調整する必要がない点です。2つのデータフレームの列名が一致していない場合や列数が異なる場合、rbindを用いることができません。しかし、この関数を用いることで、列名や列数を調整することなく結合させることができます。
rowBindの引数を以下に示します。
x | 結合させたいベクトル型またはデータフレーム型のオブジェクト |
y | xに結合させるベクトル型またはデータフレーム型のオブジェクト |
rowNames | 行名を含めるか含めないか |
colNames | 列名を含めるか含めないか |
sep | 2つのデータフレームxとyを空白行で区切って結合させるか、させないか。sep = TRUEの場合2つのデータフレームの間に空白行が挿入される。 |
colBind
関数colBindは2つの(ベクトル型かデータフレーム型)のオブジェクトを横方向に結合させる関数です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | colBind <- function(x, y, rowNames = TRUE, colNames = TRUE, sep = TRUE) { dataFrameX <- mergeRowAndColnamesWithData(x) dataFrameY <- mergeRowAndColnamesWithData(y) if (!rowNames) { dataFrameX <- as.data.frame(dataFrameX[-1, ]) rownames(dataFrameX) <- seq_len(nrow(dataFrameX)) dataFrameY <- as.data.frame(dataFrameY[-1, ]) rownames(dataFrameY) <- seq_len(nrow(dataFrameY)) } if (!colNames) { dataFrameX <- as.data.frame(dataFrameX[, -1]) colnames(dataFrameX) <- rep("", ncol(dataFrameX)) dataFrameY <- as.data.frame(dataFrameY[, -1]) colnames(dataFrameY) <- rep("", ncol(dataFrameY)) } diffOfNRow <- nrow(dataFrameX) - nrow(dataFrameY) if (diffOfNRow > 0) { emptyDataFrame <- as.data.frame(matrix(rep("", ncol(dataFrameY) * abs(diffOfNRow)), ncol = ncol(dataFrameY))) colnames(emptyDataFrame) <- rep("", ncol(emptyDataFrame)) dataFrameY <- rbind(dataFrameY, emptyDataFrame) } else { emptyDataFrame <- as.data.frame(matrix(rep("", ncol(dataFrameX) * abs(diffOfNRow)), ncol = ncol(dataFrameX))) colnames(emptyDataFrame) <- rep("", ncol(emptyDataFrame)) dataFrameX <- rbind(dataFrameX, emptyDataFrame) } bindedDataFrame <- NULL if (sep) { bindedDataFrame <- cbind(dataFrameX, rep("", nrow(dataFrameX)), dataFrameY) } else { bindedDataFrame <- cbind(dataFrameX, dataFrameY) } colnames(bindedDataFrame) <- rep("", ncol(bindedDataFrame)) return(bindedDataFrame) } |
ポイント
cbindとの違いは、行数を調整する必要がない点です。2つのデータフレームの行数が異なる場合、cbindを用いることができません。しかし、この関数を用いることで、行数を調整することなく結合させることができます。
colBindの引数を以下に示します。
x | 結合させたいベクトル型またはデータフレーム型のオブジェクト |
y | xに結合させるベクトル型またはデータフレーム型のオブジェクト |
rowNames | 行名を含めるか含めないか |
colNames | 列名を含めるか含めないか |
sep | 2つのデータフレームxとyを空白列で区切って結合させるか、させないか。sep = TRUEの場合2つのデータフレームの間に空白列が挿入される。 |
関数の使いかた
mergeRowAndColnamesWithData
関数mergeRowAndColnamesWithDataの使用例を紹介します。
データセットmtcarsにこの関数を適用してみます。
実行すると、次のようにデータフレームの1行目にはc("", "mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb")、1列目にはc("", "Mazda RX4", "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "Hornet Sportabout")となっているように、データフレームの1行目と1列目にそれぞれ行名と列名が組み込まれています。
1 2 3 4 5 6 7 8 9 | > data <- mergeRowAndColnamesWithData(mtcars) > head(data) 1 mpg cyl disp hp drat wt qsec vs am gear carb 2 Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4 3 Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 4 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1 5 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 6 Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2 |
関数rownamesやcolnamesを使うと、行名はc("1", "2", . . . , )、列名はc("", "", . . . , "")になっているのが分かります。
1 2 3 4 5 6 7 | > rownames(data) [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" [10] "10" "11" "12" "13" "14" "15" "16" "17" "18" [19] "19" "20" "21" "22" "23" "24" "25" "26" "27" [28] "28" "29" "30" "31" "32" "33" > colnames(data) [1] "" "" "" "" "" "" "" "" "" "" "" "" |
rowBind
関数rowBindの使いかたを紹介していきます。
rowBindは2つのデータフレームまたはベクトルを縦方向に結合させるときに便利です。
次を実行することで、mtcarsとirisを縦に結合できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | > data <- rowBind(mtcars, iris) > data[1 : 50, ] 1 mpg cyl disp hp drat wt qsec vs am gear carb 2 Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4 3 Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 4 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1 5 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 6 Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2 7 Valiant 18.1 6 225 105 2.76 3.46 20.22 1 0 3 1 8 Duster 360 14.3 8 360 245 3.21 3.57 15.84 0 0 3 4 9 Merc 240D 24.4 4 146.7 62 3.69 3.19 20 1 0 4 2 10 Merc 230 22.8 4 140.8 95 3.92 3.15 22.9 1 0 4 2 11 Merc 280 19.2 6 167.6 123 3.92 3.44 18.3 1 0 4 4 12 Merc 280C 17.8 6 167.6 123 3.92 3.44 18.9 1 0 4 4 13 Merc 450SE 16.4 8 275.8 180 3.07 4.07 17.4 0 0 3 3 14 Merc 450SL 17.3 8 275.8 180 3.07 3.73 17.6 0 0 3 3 15 Merc 450SLC 15.2 8 275.8 180 3.07 3.78 18 0 0 3 3 16 Cadillac Fleetwood 10.4 8 472 205 2.93 5.25 17.98 0 0 3 4 17 Lincoln Continental 10.4 8 460 215 3 5.424 17.82 0 0 3 4 18 Chrysler Imperial 14.7 8 440 230 3.23 5.345 17.42 0 0 3 4 19 Fiat 128 32.4 4 78.7 66 4.08 2.2 19.47 1 1 4 1 20 Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 21 Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.9 1 1 4 1 22 Toyota Corona 21.5 4 120.1 97 3.7 2.465 20.01 1 0 3 1 23 Dodge Challenger 15.5 8 318 150 2.76 3.52 16.87 0 0 3 2 24 AMC Javelin 15.2 8 304 150 3.15 3.435 17.3 0 0 3 2 25 Camaro Z28 13.3 8 350 245 3.73 3.84 15.41 0 0 3 4 26 Pontiac Firebird 19.2 8 400 175 3.08 3.845 17.05 0 0 3 2 27 Fiat X1-9 27.3 4 79 66 4.08 1.935 18.9 1 1 4 1 28 Porsche 914-2 26 4 120.3 91 4.43 2.14 16.7 0 1 5 2 29 Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.9 1 1 5 2 30 Ford Pantera L 15.8 8 351 264 4.22 3.17 14.5 0 1 5 4 31 Ferrari Dino 19.7 6 145 175 3.62 2.77 15.5 0 1 5 6 32 Maserati Bora 15 8 301 335 3.54 3.57 14.6 0 1 5 8 33 Volvo 142E 21.4 4 121 109 4.11 2.78 18.6 1 1 4 2 34 35 Sepal.Length Sepal.Width Petal.Length Petal.Width Species 36 1 5.1 3.5 1.4 0.2 setosa 37 2 4.9 3 1.4 0.2 setosa 38 3 4.7 3.2 1.3 0.2 setosa 39 4 4.6 3.1 1.5 0.2 setosa 40 5 5 3.6 1.4 0.2 setosa 41 6 5.4 3.9 1.7 0.4 setosa 42 7 4.6 3.4 1.4 0.3 setosa 43 8 5 3.4 1.5 0.2 setosa 44 9 4.4 2.9 1.4 0.2 setosa 45 10 4.9 3.1 1.5 0.1 setosa 46 11 5.4 3.7 1.5 0.2 setosa 47 12 4.8 3.4 1.6 0.2 setosa 48 13 4.8 3 1.4 0.1 setosa 49 14 4.3 3 1.1 0.1 setosa 50 15 5.8 4 1.2 0.2 setosa |
また、ベクトルに対しても同様の操作が可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | > data <- rowBind(c(1 ,2, 3, 4, 5), mtcars) > data[1 : 20, ] 1 1 2 2 3 3 4 4 5 5 6 7 mpg cyl disp hp drat wt qsec vs am gear carb 8 Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4 9 Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 10 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1 11 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 12 Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2 13 Valiant 18.1 6 225 105 2.76 3.46 20.22 1 0 3 1 14 Duster 360 14.3 8 360 245 3.21 3.57 15.84 0 0 3 4 15 Merc 240D 24.4 4 146.7 62 3.69 3.19 20 1 0 4 2 16 Merc 230 22.8 4 140.8 95 3.92 3.15 22.9 1 0 4 2 17 Merc 280 19.2 6 167.6 123 3.92 3.44 18.3 1 0 4 4 18 Merc 280C 17.8 6 167.6 123 3.92 3.44 18.9 1 0 4 4 19 Merc 450SE 16.4 8 275.8 180 3.07 4.07 17.4 0 0 3 3 20 Merc 450SL 17.3 8 275.8 180 3.07 3.73 17.6 0 0 3 3 |
ベクトル同士でも、次のように結合させることができます。
1 2 3 4 5 6 7 8 9 10 | > data <- rowBind(c(1 ,2, 3, 4, 5), t(letters[1 : 10])) > data 1 1 2 2 3 3 4 4 5 5 6 7 a b c d e f g h i j |
colBind
最後に、関数colBindの使いかたを紹介していきます。
rowBindとは反対に、colBindは2つのデータフレームやベクトルを横方向に結合させることができます。
次のように横方向に連結することが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | data <- colBind(mtcars, iris) > head(data) 1 mpg cyl disp hp drat wt qsec vs am gear carb Sepal.Length Sepal.Width Petal.Length 2 Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4 1 5.1 3.5 1.4 3 Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 2 4.9 3 1.4 4 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1 3 4.7 3.2 1.3 5 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 4 4.6 3.1 1.5 6 Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2 5 5 3.6 1.4 1 Petal.Width Species 2 0.2 setosa 3 0.2 setosa 4 0.2 setosa 5 0.2 setosa 6 0.2 setosa |
rowBindの時と同様に、ベクトルに対してもcolBindを用いることができます。
1 2 3 4 5 6 7 8 9 | > data <- colBind(c(1, 2, 3, 4, 5), mtcars) > head(data) 1 1 mpg cyl disp hp drat wt qsec vs am gear carb 2 2 Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4 3 3 Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 4 4 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1 5 5 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 6 Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2 |
ダウンロード方法
今回紹介した関数はR言語自作パッケージUsagiSanをインストールすることで使えます。
R言語 自作パッケージ UsagiSan
こんにちは、usagi-sanです。 R言語の自作パッケージを紹介します。 統計解析のアルバイトをしている中、暇な時間を見つけて自分でパッケージを作ってみました。 Rのパッケージには、統計解析用のパッ ...
続きを見る
ここで紹介した関数以外にも、便利な関数が沢山あります。ぜひぜひ、使ってください。
また、以下のダウンロードリンクからこの関数を含むスクリプトファイルをダウンロードすることができます。
まとめ
ベクトルやデータフレームを簡単に結合できる関数を導入してみました。
Rに標準で入っている関数rbindやcbindよりも、柔軟性が高く直感的にデータフレームを操作することができます。
また、row.names = FALSEやcol.names = FALSEとの相性も良く、位置などがずれることなく行名や列名がデータフレームの要素に組み込むことができます。
データフレームの操作に役立ててください。