複数の列の名前を名前で変更する


84

誰かがすでにこれを尋ねるべきでしたが、私は答えを見つけることができませんでした。私が持っていると言う:

x = data.frame(q=1,w=2,e=3, ...and many many columns...)  

位置が必ずしもわからない列の任意のサブセットの名前を他の任意の名前に変更する最もエレガントな方法は何ですか?

たとえば、名前を変更"q""e""A"andに変更したい"B"場合、これを行うための最もエレガントなコードは何ですか?

明らかに、私はループを行うことができます:

oldnames = c("q","e")
newnames = c("A","B")
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i]

しかし、もっと良い方法があるのだろうか?たぶんいくつかのパッケージを使用していますか?(plyr::renameなど)

回答:


106

setnamesdata.tableパッケージからはdata.framesまたはdata.tablesで動作します

library(data.table)
d <- data.frame(a=1:2,b=2:3,d=4:5)
setnames(d, old = c('a','d'), new = c('anew','dnew'))
d


 #   anew b dnew
 # 1    1 2    4
 # 2    2 3    5

変更は参照によって行われるため、コピーは行われないことに注意してください(data.framesの場合でも!)


1
ここに遅れて到着した場合old = c("a", "d", "e")
micstr 2016年

1
すべてではなくサブセット/一部の列の名前を変更したいだけの場合、これは機能しますか?したがって、10列のデータフレームがあり、_id_firstnameをfirstnameに、_ id_lastnameをlastnameに名前変更したいが、残りの8列はそのままにしておく場合、これを行うことはできますか、それともすべての列を一覧表示する必要がありますか?
Mus 2018

@MusTheDataGuy新しい名前と古い名前のサブセットを指定すると、機能します。
mnel

@mnel @Musが尋ねたように、サブセットの変数名を変更する必要があります。ただし、上記のコードはデータのサブセットに対しては機能しませんでした。@Gorkaの答えrename_at()は、サブセットの変数名を変更するために機能しました。
MehmetYildirim20年

95

dplyrを使用すると、次のようになります。

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)
    
df %>% rename(A = q, B = e)

#  A w B
#1 1 2 3

または、@ Jelena-bioinfによって提案されているように、ベクトルを使用する場合:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)

oldnames = c("q","e")
newnames = c("A","B")

df %>% rename_at(vars(oldnames), ~ newnames)

#  A w B
#1 1 2 3

LD Nicolas Mayは、与えられた変更rename_atは次のものに取って代わられることを示唆しましたrename_with

df %>% 
  rename_with(~ newnames[which(oldnames == .x)], .cols = oldnames)

#  A w B
#1 1 2 3

2
ユーザーは渡しについて尋ねたoldnewベクトル、私が考えるような名前
JelenaČuklina

4
@ Jelena-bioinfに感謝します。私はあなたの提案を含むように答えを修正しました。
ゴルカ2018年

〜(チルダ)の意味と、rename_withの例で「.x」がどこから来ているのか説明していただけますか?
ペッツィ

rename_with 関数または数式のいずれかを使用して、として指定されたすべての列の名前を変更できます .cols引数。たとえば、rename_with(iris, toupper, starts_with("Petal"))と同等rename_with(iris, ~ toupper(.x), starts_with("Petal"))です。
PaulRougieux20年

38

大きすぎないデータフレームの別の解決策は(@thelatemailの回答に基づいて):

x <- data.frame(q=1,w=2,e=3)

> x
  q w e
1 1 2 3

colnames(x) <- c("A","w","B")

> x
  A w B
1 1 2 3

または、次を使用することもできます。

names(x) <- c("C","w","D")

> x
  C w D
1 1 2 3

さらに、列名のサブセットの名前を変更することもできます。

names(x)[2:3] <- c("E","F")

> x
  C E F
1 1 2 3

25

これは、purrr::set_names()いくつかのstringr操作の組み合わせを使用して複数の列の名前を変更するために私が見つけた最も効率的な方法です。

library(tidyverse)

# Make a tibble with bad names
data <- tibble(
    `Bad NameS 1` = letters[1:10],
    `bAd NameS 2` = rnorm(10)
)

data 
# A tibble: 10 x 2
   `Bad NameS 1` `bAd NameS 2`
   <chr>                 <dbl>
 1 a                    -0.840
 2 b                    -1.56 
 3 c                    -0.625
 4 d                     0.506
 5 e                    -1.52 
 6 f                    -0.212
 7 g                    -1.50 
 8 h                    -1.53 
 9 i                     0.420
 10 j                     0.957

# Use purrr::set_names() with annonymous function of stringr operations
data %>%
    set_names(~ str_to_lower(.) %>%
                  str_replace_all(" ", "_") %>%
                  str_replace_all("bad", "good"))

# A tibble: 10 x 2
   good_names_1 good_names_2
   <chr>               <dbl>
 1 a                  -0.840
 2 b                  -1.56 
 3 c                  -0.625
 4 d                   0.506
 5 e                  -1.52 
 6 f                  -0.212
 7 g                  -1.50 
 8 h                  -1.53 
 9 i                   0.420
10 j                   0.957

6
これが答えになるはずですが、パイプ内の引数~.引数が何をするかについても拡張する必要がありset_names()ます。
DaveRGP 2018年

場合によっては、明示的に入力する必要がありますpurrr::set_names()
LeviBaguley20年

1
@DaveRGPpurrr関数を使用する場合、チルダ~は「各列」を意味します。.すなわち、この場合には、パイプされたオブジェクトへの参照LHS =管の左側用dplyr構文ですdata
アジャイルビーン

チルダ~は公式です。関数呼び出しを使用して、引数を引数に渡すこともできます。たとえば、...はと同等です。set_namesrlang::set_names(head(iris), paste0, "_hi")rlang::set_names(head(iris), ~ paste0(.x, "_hi"))
PaulRougieux20年

11

そのため、最近、列が存在するかどうかわからず、存在する列の名前を変更したいだけの場合は、自分でこれに遭遇しました。

existing <- match(oldNames,names(x))
names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]

6

@ user3114046の答えに基づいて構築:

x <- data.frame(q=1,w=2,e=3)
x
#  q w e
#1 1 2 3

names(x)[match(oldnames,names(x))] <- newnames

x
#  A w B
#1 1 2 3

これは、xデータセット内の列の特定の順序に依存しません。


1
私はあなたの答えに賛成しましたが、これを行うためのさらにエレガントな方法、特に位置ではなく名前で名前を変更する方法があるかどうか疑問に思います
qoheleth 2014年

@ qoheleth-名前で名前を変更しています!ここには、それを処理する位置ベクトルである入力はありませんmatch。あなたがやろうとしている最善のことは、おそらく@mnelのsetnames答えでしょう。
thelatemail 2014年

1
あなたが言ったように、私が位置ベクトルを明示的に指定する必要がないのに、それはまだ位置による一種の名前変更です、 matchはまだ位置指向のコマンドであるです。この精神で、私は@ user3114046の回答位置も同様に基づいていると見なしました(%in%コマンドが物事を処理する(またはしようとする)とはいえ)。もちろん、低レベルのメカニズムにドリルダウンすると、すべてのコマンドが位置指向であると主張できると思いますが、それは私が言っていることではありません... data.tableの答えは、複数の呼び出しがないので素晴らしいです。nameコマンド。
qoheleth 2014年

4

これにより、すべての名前で出現するすべての文字が変更されます。

 names(x) <- gsub("q", "A", gsub("e", "B", names(x) ) )

2
いくつかの名前変更インスタンスを通過した後は、これは特にエレガントではないと思います。
thelatemail 2014年

私はgsubfn答えを出すのに十分ではありません。おそらくG.Grothendieckがやってくるでしょう。彼は正規表現マイスターです。
IRTFM 2014年

4
names(x)[names(x) %in% c("q","e")]<-c("A","B")

2
私が言ったように、私は必ずしも列の位置を知らないので、完全ではありません。あなたのソリューションoldnamesは、i <jのoldnames[i]oldnames[j]に発生するようにソートされている場合にのみ機能します。
qoheleth 2014年

2

名前セットを取得してリストとして保存し、文字列の名前を一括変更することができます。これの良い例は、データセットで長い遷移から広い遷移を実行している場合です。

names(labWide)
      Lab1    Lab10    Lab11    Lab12    Lab13    Lab14    Lab15    Lab16
1 35.75366 22.79493 30.32075 34.25637 30.66477 32.04059 24.46663 22.53063

nameVec <- names(labWide)
nameVec <- gsub("Lab","LabLat",nameVec)

names(labWide) <- nameVec
"LabLat1"  "LabLat10" "LabLat11" "LabLat12" "LabLat13" "LabLat14""LabLat15"    "LabLat16" " 

2

ちなみに、1つの文字列をすべての列名に連結する場合は、この単純なコードを使用できます。

colnames(df) <- paste("renamed_",colnames(df),sep="")

2

テーブルに同じ名前の2つの列が含まれている場合、コードは次のようになります。

rename(df,newname=oldname.x,newname=oldname.y)

2

名前付きベクトルを使用できます。

ベースRの場合(多分やや不格好):

x = data.frame(q = 1, w = 2, e = 3) 

rename_vec <- c(q = "A", e = "B")

names(x) <- ifelse(is.na(rename_vec[names(x)]), names(x), rename_vec[names(x)])

x
#>   A w B
#> 1 1 2 3

または:dplyr付きのオプション!!!

library(dplyr)

rename_vec <- c(A = "q", B = "e") # the names are just the other way round than in the base R way!

x %>% rename(!!!rename_vec)
#>   A w B
#> 1 1 2 3

後者は、「ビッグバン」演算子!!!がリストまたはベクトルの評価を強制しているために機能します。

?`!!`

!!! force-オブジェクトのリストをスプライスします。リストの要素は所定の位置でスプライスされます。つまり、それぞれが1つの引数になります。


これがどのように機能するかを理解していません-!!!oldnames戻りますc("A", "B")が、どのロジックがこれをc("A", "w", "B")??
アジャイルビーン

@AgileBean !!! oldnamesがベクトルを返すことがどこで見つかったかわかりません。これは、dplyrの複数の引数の非標準評価を強制するために使用されます。を参照してください?`!!` Use `!!!` to add multiple arguments to a function. Its argument should evaluate to a list or vector: args <- list(1:3, na.rm = TRUE) ; quo(mean(!!!args))。この説明を答えに加えようと思います。それを育てるために乾杯
tjeboを

1

たくさんの答えがあるので、コピーして貼り付けることができるように関数を作成しました。

rename <- function(x, old_names, new_names) {
    stopifnot(length(old_names) == length(new_names))
    # pull out the names that are actually in x
    old_nms <- old_names[old_names %in% names(x)]
    new_nms <- new_names[old_names %in% names(x)]

    # call out the column names that don't exist
    not_nms <- setdiff(old_names, old_nms)
    if(length(not_nms) > 0) {
        msg <- paste(paste(not_nms, collapse = ", "), 
            "are not columns in the dataframe, so won't be renamed.")
        warning(msg)
    }

    # rename
    names(x)[names(x) %in% old_nms] <- new_nms
    x
}

 x = data.frame(q = 1, w = 2, e = 3)
 rename(x, c("q", "e"), c("Q", "E"))

   Q w E
 1 1 2 3

rename(x, c("q", "e"), c("Q", "E"))dplyrの名前変更で機能しなくなったようですか?
sindri_baldur 2018年

0

データの1行に名前が含まれている場合は、すべての列を変更できます。

names(data) <- data[row,]

与えられたのdataはあなたのデータフレームとrow、新しい値を含む行番号です。

次に、名前を含む行を削除できます。

data <- data[-row,]

0

これは必要な関数です。次に、rename(X)でxを渡すだけで、表示されるすべての値の名前が変更され、そこにない場合でもエラーは発生しません。

rename <-function(x){
  oldNames = c("a","b","c")
  newNames = c("d","e","f")
  existing <- match(oldNames,names(x))
  names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
  return(x)
}

1
これは同じであるように思わJoelKuiperの答え.....が、その後、関数として再フレーミング
ヤープ

0

機能dplyr::rename_withrlang::set_namesすでに言及しているいくつかの答えがあります。それらによって別々です。この回答は、2つの違いと、列の名前を変更するための関数と数式の使用を示しています。

rename_withdplyrパッケージから、関数または式のいずれかを使用して、.cols引数として指定された列の選択の名前を変更できます。たとえば、関数名を渡すtoupper

library(dplyr)
rename_with(head(iris), toupper, starts_with("Petal"))

式を渡すことと同等です~ toupper(.x)

rename_with(head(iris), ~ toupper(.x), starts_with("Petal"))

すべての列の名前を変更する場合set_namesは、rlangパッケージからも使用できます。別の例を作るために、paste0名前変更関数として使用してみましょう。pasteO2つの引数を取ります。その結果、関数と式のどちらを使用するかに応じて、2番目の引数を渡す方法が異なります。

rlang::set_names(head(iris), paste0, "_hi")
rlang::set_names(head(iris), ~ paste0(.x, "_hi"))

同じことrename_withは、データフレームを最初の引数.dataとして、関数を2番目の引数として.fn、すべての列を3番目の引数として.cols=everything()、関数パラメーターを4番目の引数として渡すことで実現できます...。または、2番目、3番目、4番目の引数を、2番目の引数として指定された数式に配置することもできます。

rename_with(head(iris), paste0, everything(), "_hi")
rename_with(head(iris), ~ paste0(.x, "_hi"))

rename_withデータフレームでのみ機能します。set_namesより一般的で、ベクトルの名前変更も実行できます

rlang::set_names(1:4, c("a", "b", "c", "d"))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.