jnobuyukiのブログ

JavaScriptとR言語を中心に研究活動に役立つwebアプリケーション技術について考えていきます。twitter ID: @j_nobuyuki

行列やデータフレームの列名・変数名の変更

R言語で作業をしていて、つまらないことに時間がかかったので、次回以降の作業用にメモしておきます。

列名、変数名の取得と設置:colnames(),names()

R言語では、データ行列を保存できるオブジェクトが二種類あります。行列(matrix)とデータフレーム(data.frame)です。どちらもcolnames()かnames()で列名、変数名を取得・設定できます。でも、いわゆるGetSet関数とは違い、少しクセがあります。それぞれのオブジェクトでcolnames()の動作を見てみましょう*1

行列オブジェクトの場合

まずmatrix()でオブジェクトを作ってみます。

mat <- matrix(1:12, nrow = 3, ncol = 4)
print(data)


[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12

表の一番上の行に変数名を設定することを考えます。

この段階でcolnames(mat)を使用してみます。Getに相当するのですが、値としてNULLが返ります。まだ名前を全く設定していないので、当然です。では同じ関数で変数名を設定してみましょう。例えば最初の2列に名前をつけたい場合、colnames(mat) <- c("A","B")とすると次のようなエラーが返ります。

Error in `colnames<-`(`*tmp*`, value = c("A", "B")) : 
  length of 'dimnames' [2] not equal to array extent

エラーメッセージはどうやら、名前の数と列の数が一致しなければならないと言っているようです。そこで

colnames(mat) <- c("A","B","C","D")

としてみましょうすると、今度はエラーなしで動作します。結果として

A B C D
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12

このように、行列に名前が付きます。ここで注意したいのは、変数の1つを選んで、その名前を上書きしようとしても上手くいかないことです。例えば、

colnames(mat[3]) <- "c" 

とすると

Error in `colnames<-`(`*tmp*`, value = "c") : 
   次元が 2 未満のオブジェクトに 'colnames' を設定しようとしました 

このようなエラーが返ります。他のGETSET関数だったらこんな使い方もできそうなのですが、Rのcolnames()では、行列全体の名前を設定する必要がありそうです。

データフレームオブジェクトの場合

まずはデータフレームオブジェクトを作成します。さきほどの行列オブジェクトを変換します。

dat <- as.data.frame(mat)
print(dat)


V1 V2 V3 V4
1 1 4 7 10
2 2 5 8 11
3 3 6 9 12

今度は何も設定しないうちからV1~V4の名前がついています。colnames(dat)とすると、"V1" "V2" "V3" "V4"という答えが返ります。データフレームの場合も全ての変数を一括で設定できます。

colnames(dat) <- c("A","B","C","D")

では、一つだけを変更することができるでしょうか?試しにcolnames(dat[3])<- "c"とします。この場合、何のエラーも返ってきませんが、colnames(dat)で変数名を取得すると"A" "B" "C" "D"が返ります。つまり、上書きされないです。
ただし次のようなやり方をすると変数名が変化します。

colnames(dat) <- "a"

これを実行して、変数名を取得すると"a" NA NA NAとなるんです。つまり、最初の一つだけでなく、それ以外の変数名がNA(つまり使用不可能)になってしまうことになります。

まとめ:変数名の上書きは、オブジェクト全体で。

行列オブジェクトでもデータフレームオブジェクトでも変数名を上書きで変更する際には、変えたい変数名だけではなく、全ての変数名を入れ直す必要があります。エラーメッセージがいつでも返ってくるわけではないことにも注意しましょう。

*1:今回はnames()を取りあげませんが、動作はcolnames()と同じです。またrownames()というのもあります。