備忘ログ

チラシの裏的備忘録&メモ

Rでdplyrをつかって任意の列の列名を変更する方法

dplyrで列名を変更する

Rでdplyrパッケージで用意されているdplyr::selectやdplyr::renameをつかってデータフレームの任意の列の列名を書き換えてみる。

ときどき忘れちゃうのでメモ

baseのcolnamesでの列名の変更は下記。

indenkun.hatenablog.com

dplyrはinstall.package()でtidyverseでまとめか、dplyrのみをインストールしておく。

dplyr::selectでできらぁ

# 適当なデータフレームを作る
d <- data.frame(matrix(1:12, c(3,4)))
d
##   X1 X2 X3 X4
## 1  1  4  7 10
## 2  2  5  8 11
## 3  3  6  9 12

そうすると列名を決めていないとX1、X2…という列名が入るのでこれを直したいときにdplyr::selectを使う場合。

X1をID、X2をNumberとしてみて、ほかすべてはそのままにしたい場合。

d <- dplyr::select(d, ID = X1, Number =  X2, dplyr::everything())
d
##   ID Number X3 X4
## 1  1      4  7 10
## 2  2      5  8 11
## 3  3      6  9 12

でいける。

列名で指定する場合はフルスペルで書く必要があり、タイポするとエラーがでる。

列番号でも行ける。

d <- data.frame(matrix(1:12, c(3,4)))
d <- dplyr::select(d, ID = 1, Number = 2, dplyr::everything())
d
##   ID Number X3 X4
## 1  1      4  7 10
## 2  2      5  8 11
## 3  3      6  9 12

あとは、

d <- data.frame(matrix(1:12, c(3,4)))
d <- dplyr::select(d, X1 = X2, dplyr::everything())
## Error: Names must be unique.
## [31mx[39m These names are duplicated:
##   * "X1" at locations 1 and 2.

という感じですでに同じ列名をもつデータフレームはつくられない。

同じデータフレーム内に同じ列名がなければいいので、列を取り出してもとのデータフレームにある別の列の名前をつけても、その列を取り出していなければ問題ない。

d <- data.frame(matrix(1:12, c(3,4)))
d <- dplyr::select(d, X1 = X2)
d
##   X1
## 1  4
## 2  5
## 3  6

dplyr::renameでできらぁ

dplyr::renameを使ってやってみる。最初の一列目をIDに、二列目をNumberに変えたい場合。

d <- data.frame(matrix(1:12, c(3,4)))
d <- dplyr::rename(d, ID = X1, Number = X2)
d
##   ID Number X3 X4
## 1  1      4  7 10
## 2  2      5  8 11
## 3  3      6  9 12

dplyr::selectとの比較でdplyr::renameのいいところは、次のを実行するとわかるが、

d <- data.frame(matrix(1:12, c(3,4)))
d <- dplyr::rename(d, Number = X2)
d
##   X1 Number X3 X4
## 1  1      4  7 10
## 2  2      5  8 11
## 3  3      6  9 12

と順番がもとのデータと同じ並びのままになるし、dplyr::everything()を使わなくても、名前を変えていないすべてでてくるところ。

逆にいうと、dplyr::selectだと、選んだものだけ(もともとそういうやつだし)、選んだ順番で行けるのがいいところ。

dplyr::renameもデータフレーム内にある同じ列名はつけられない。

d <- data.frame(matrix(1:12, c(3,4)))
d <- dplyr::rename(d, X4 = X1, X3 = X2)
## Error: Names must be unique.
## [31mx[39m These names are duplicated:
##   * "X4" at locations 1 and 4.
##   * "X3" at locations 2 and 3.

おまけ

d <- data.frame(matrix(1:12, c(3,4)))
colnames(d)[1:4] <- "ID"
d
##   ID ID ID ID
## 1  1  4  7 10
## 2  2  5  8 11
## 3  3  6  9 12

ですべての列名が同じになったときdplyr::renameだと2列目の列名IDをidに変えようとしても

dplyr::rename(d, id = ID)
## Error: Can't rename duplicate variables to `{name}`.
dplyr::rename(d, id = 2)
## Error: Names must be unique.
## [31mx[39m These names are duplicated:
##   * "ID" at locations 1, 3, and 4.

列名指定はもちろんのこと、列番号してもエラーがでてしまい名前が変えられない。

dplyr::selectも列名指定だと、dplyr::renameと同じエラーがでるし、dplyr::everything()で残りの列を取り出したりするとdplyr::renameと同じで同じ名前がいっぱいあるよ、と怒られる。

回避策としてはdplyr::selectで列名指定で列名を変えてそれだけ取り出すか、他の列も取り出すときには列番号指定で他の列も同じ列名がデータフーム内に存在しないように調整するといける。

dplyr::select(d, 1, id = 2, ID2 = 3, ID3 = 4)
##   ID id ID2 ID3
## 1  1  4   7  10
## 2  2  5   8  11
## 3  3  6   9  12

documentを探ったわけじゃないけど、tidyverseの設計思想として同一データフレーム内に同じ列名を入れてくれるなというのが透けて見える気がする。

普通に考えて分析対象のデータフレーム内に同じ名前があるべきではないし、あったとしても添え字か添え数字をつけて区別できるようにすべき。

もちろんbaseのcolnamesなら

d <- data.frame(matrix(1:12, c(3,4)))
colnames(d)[1:4] <- "ID"
colnames(d)[2] <- "id"
d
##   ID id ID ID
## 1  1  4  7 10
## 2  2  5  8 11
## 3  3  6  9 12

と選んだ列の列名を書き換えられる。

あとdplyr::selectやdplyr::renameは列名がNAだとNAのままだと取り出せないので、その点も設計思想の差かもしれない。

これも普通に考えて、列名がNAのままだと扱いにくいのでbase正しい判断ではあると思うが、柔軟さ的にはbaseのほうが柔軟かも。