按名称重命名多个列

时间:2014-01-08 04:52:08

标签: r dataframe rename r-faq

有人应该已经问过这个,但我找不到答案。说我有:

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

将列表的任意子集(我不一定知道的位置)重命名为其他任意名称的最优雅方法是什么?

e.g。假设我想将"q""e"重命名为"A""B",最优雅的代码是什么?

显然,我可以做一个循环:

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

但我想知道是否有更好的方法?也许使用一些包? (plyr::rename等。)

18 个答案:

答案 0 :(得分:80)

来自setnames包的

data.table适用于data.framedata.table

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 :(得分:48)

使用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

答案 2 :(得分:29)

另一个不太大的数据帧解决方案是(基于@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

答案 3 :(得分:11)

所以我最近遇到了这个问题,如果您不确定列是否存在且只想重命名那些:

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

答案 4 :(得分:7)

以下是我发现使用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

答案 5 :(得分:5)

建立在@ 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数据集中列的特定顺序。

答案 6 :(得分:4)

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

答案 7 :(得分:4)

这将改变所有名称中出现的所有字母:

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

答案 8 :(得分:2)

您可以获取名称集,将其另存为列表,然后对字符串进行批量重命名。一个很好的例子就是当您在数据集上进行长到大的转换时:

        myGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50) });
        myGrid.ColumnDefinitions.Add(new ColumnDefinition());
        myGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50) });

        Border b1 = new Border
        {
            Background = new SolidColorBrush(Colors.Blue),
            CornerRadius = new CornerRadius(100, 0, 0, 100)
        };

        Grid.SetColumn(b1, 0);

        Border b2 = new Border
        {
            Background = new SolidColorBrush(Colors.Blue),
        };
        Grid.SetColumn(b2, 1);
        Border b3 = new Border
        {
            Background = new SolidColorBrush(Colors.Blue),
            CornerRadius = new CornerRadius(0, 100, 100, 0),
        };
        Grid.SetColumn(b3, 2);

        myGrid.Children.Add(b1);
        myGrid.Children.Add(b2);
        myGrid.Children.Add(b3);

答案 9 :(得分: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

答案 10 :(得分:1)

更新 dplyr 1.0.0

最新的 dplyr 版本通过添加 rename_with() 变得更加灵活,其中 _with 指的是作为输入的函数。 技巧是将字符向量 newnames 重新表示为公式(通过 ~),因此它等效于 function(x) return (newnames)

在我看来,这是最优雅的 dplyr 表达。

# shortest & most elegant expression
df %>% rename_with(~ newnames, oldnames)

A w B
1 1 2 3

旁注:

如果颠倒顺序,则参数 .fn 必须指定为 .fn 应在 .cols 参数之前。

df %>% rename_with(oldnames, .fn = ~ newnames)

A w B
1 1 2 3

答案 11 :(得分:1)

您可以使用命名向量。

以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的{​​{1}}选项:

!!!

后者之所以有效,是因为'big-bang'运算符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 强制评估列表或向量。

!!!

!!!强制拼接对象列表。列表中的元素是 拼接到位,意味着它们每个都成为一个单独的参数。

答案 12 :(得分:1)

如果表包含两个具有相同名称的列,则代码如下所示,

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

答案 13 :(得分:1)

旁注,如果你想将一个字符串连接到所有列名,你可以使用这个简单的代码。

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

答案 14 :(得分:0)

这是您需要的功能: 然后只需将x传递给rename(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)
}

答案 15 :(得分:0)

有一些答案已经提到了功能dplyr::rename_withrlang::set_names。通过它们是分开的。这个答案说明了两者之间的区别以及使用函数和公式重命名列的区别。

rename_with包中的

dplyr可以使用函数或公式 重命名作为.cols参数给出的选择列。例如,传递函数名称toupper

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

等效于传递公式~ toupper(.x)

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

重命名所有列时,还可以使用rlang包中的set_names。举一个不同的例子,让我们使用paste0作为重命名函数。 pasteO接受2个参数,因此根据我们使用的是函数还是公式,有不同的方式传递第二个参数。

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

rename_with可以通过首先传递数据帧来实现相同的目的 参数.data,函数作为第二个参数.fn,所有列作为第三列 参数.cols=everything()和函数参数作为第四个参数 参数...。或者,您可以放置​​第二,第三和第四 公式中的参数作为第二个参数。

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"))

答案 16 :(得分:0)

如果一行数据包含您要更改所有列的名称,则可以执行

names(data) <- data[row,]

鉴于data是您的数据框,row是包含新值的行号。

然后,您可以删除包含

名称的行
data <- data[-row,]

答案 17 :(得分:0)

上面使用专门的软件包提供了许多好的答案。这是仅使用基础 R 的简单方法。

df.rename.cols <- function(df, col2.list) {
  tlist <- transpose(col2.list)
    
  names(df)[which(names(df) %in% tlist[[1]])] <- tlist[[2]]

  df
} 

这是一个例子:

df1 <- data.frame(A = c(1, 2), B = c(3, 4), C = c(5, 6), D = c(7, 8))
col.list <- list(c("A", "NewA"), c("C", "NewC"))
df.rename.cols(df1, col.list)

  NewA B NewC D
1    1 3    5 7
2    2 4    6 8
相关问题