17

元の名前を使用して参照するデータフレームの 1 つの列を更新したいのですが、これは可能ですか? たとえば、テーブル「データ」があるとします

a b c  
1 2 2  
3 2 3  
4 1 2

列bの名前を「d」に更新したかったのです。私は私が使用できることを知っています

colnames(data)[2] <- 'd'  

しかし、具体的にbを参照することで変更できますか、つまり次のようなものです

colnames(data)['b'] <- 'd'  

データフレームの列の順序が変更された場合でも、正しい列名が更新されるようにします。

前もって感謝します

4

5 に答える 5

30

まさにそのための機能setnamesがパッケージに組み込まれています。data.table

setnames(DT, "b", "d")

コピーなしで参照によって名前を変更します。names(data)<-またはnames(data)[i]<-類似のものを使用する他の方法では、オブジェクト全体が通常数回コピーされます。あなたがしているのは列名を変更することだけですが。

DTただし、機能するには型data.tableでなければなりませんsetnames。したがって、使用するには、に切り替えるdata.tableか、変換する必要がありas.data.tableます。

からの抜粋です?setnames。意図は、プロンプトで実行するexample(setnames)と、コメントが によって報告されているコピーに関連することですtracemem

DF = data.frame(a=1:2,b=3:4)       # base data.frame to demo copies
tracemem(DF)
colnames(DF)[1] <- "A"             # 4 copies of entire object
names(DF)[1] <- "A"                # 3 copies of entire object
names(DF) <- c("A", "b")           # 2 copies of entire object
`names<-`(DF,c("A","b"))           # 1 copy of entire object
x=`names<-`(DF,c("A","b"))         # still 1 copy (so not print method)

# What if DF is large, say 10GB in RAM. Copy 10GB just to change a column name?

DT = data.table(a=1:2,b=3:4,c=5:6)
tracemem(DT)
setnames(DT,"b","B")               # by name; no match() needed. No copy.
setnames(DT,3,"C")                 # by position. No copy.
setnames(DT,2:3,c("D","E"))        # multiple. No copy.
setnames(DT,c("a","E"),c("A","F")) # multiple by name. No copy.
setnames(DT,c("X","Y","Z"))        # replace all. No copy.
于 2012-05-18T16:02:52.817 に答える
14

2014 年 10 月の時点で、これはdplyrパッケージで簡単に実行できるようになりました。

rename(data, d = b)
于 2015-01-19T14:20:25.937 に答える
13

これはハックのように思えますが、最初に頭に浮かんだのはgrepl()、十分に詳細な検索文字列を使用して、必要な列のみを取得することでした。より良いオプションがあると確信しています:

dat <- data.frame(a = 1:3, b = 1:3, c = 1:3)
colnames(dat)[grepl("b", colnames(dat))] <- "foo"
dat
#------
  a foo c
1 1   1 1
2 2   2 2
3 3   3 3

Joran が以下で指摘しているように、私は物事を複雑にしすぎました...正規表現はまったく必要ありません。これにより、入力する文字数も節約されます。

colnames(dat)[colnames(dat) == "foo"] <- "bar"
#------
  a bar c
1 1   1 1
2 2   2 2
3 3   3 3
于 2012-05-18T15:36:02.433 に答える
3

はい、しかしそれは(私が知る限り)数値インデックスよりも難しいです。これを行うダーティ関数を提供します。その方法を確認したい場合は、関数を 1 行ずつ分割してください。

rename <- function(df, column, new){
    x <- names(df)                               #Did this to avoid typing twice
    if (is.numeric(column)) column <- x[column]  #Take numeric input by indexing
    names(df)[x %in% column] <- new              #What you're interested in
    return(df)
}

#try it out
rename(mtcars, 'mpg', 'NEW')
rename(mtcars, 1, 'NEW')
于 2012-05-18T15:34:28.893 に答える
1

私は@Chaseに同意しませgreplん-解決策は最も幸運なものではありません。私は言います:シンプルに行き==ます。理由は次のとおりです。

d <- data.frame(matrix(rnorm(100), 10))
colnames(d) <- replicate(10, paste(sample(letters[1:5], size = 5, replace=TRUE, prob=c(.1, .6, .1, .1, .1)), collapse = ""))

やってみてくださいgrepl("b", colnames(d))。パスするか、 @joran が提案したようfixed = TRUEにシンプルにすることをお勧めします。colnames(d) == "b"正規表現マッチングは常によりも遅くなる==ため、このような単純なタスクには simple を使用することをお勧めします==

于 2012-05-18T15:59:43.477 に答える