qoh*_*eth 63 r rename dataframe r-faq
有人应该已经问过这个,但我找不到答案.说我有:
x = data.frame(q=1,w=2,e=3, ...and many many columns...)
Run Code Online (Sandbox Code Playgroud)
将我不一定知道的位置的任意子列重命名为其他任意名称的最优雅方法是什么?
例如说我要重新命名"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]
Run Code Online (Sandbox Code Playgroud)
但我想知道是否有更好的方法?也许使用一些包?(plyr::rename等)
mne*_*nel 87
setnames从data.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
Run Code Online (Sandbox Code Playgroud)
请注意,更改是通过引用进行的,因此不进行复制(即使对于data.frames!)
Gor*_*rka 65
使用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
Run Code Online (Sandbox Code Playgroud)
或者如果你想使用载体,正如@ 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
Run Code Online (Sandbox Code Playgroud)
Agi*_*ean 32
最新的 dplyr 版本通过添加rename_with()where_with 引用函数作为输入而变得更加灵活。诀窍是将字符向量重新表述为newnames公式 (by ~),因此它相当于function(x) return (newnames)。
在我主观看来,这是最优雅的 dplyr 表达方式。更新:感谢@desval,oldnames 向量必须包含在其中all_of以包含其所有元素:
# shortest & most elegant expression
df %>% rename_with(~ newnames, all_of(oldnames))
A w B
1 1 2 3
Run Code Online (Sandbox Code Playgroud)
如果颠倒顺序,则必须指定任一参数 .fn,因为 .fn 应该在 .cols 参数之前:
df %>% rename_with(oldnames, .fn = ~ newnames)
A w B
1 1 2 3
Run Code Online (Sandbox Code Playgroud)
或指定参数 .col:
df %>% rename_with(.col = oldnames, ~ newnames)
A w B
1 1 2 3
Run Code Online (Sandbox Code Playgroud)
Jaa*_*aap 31
另一个不太大的数据帧解决方案是(基于@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
Run Code Online (Sandbox Code Playgroud)
或者,您也可以使用:
names(x) <- c("C","w","D")
> x
C w D
1 1 2 3
Run Code Online (Sandbox Code Playgroud)
此外,您还可以重命名列名的子集:
names(x)[2:3] <- c("E","F")
> x
C E F
1 1 2 3
Run Code Online (Sandbox Code Playgroud)
Mat*_*cho 15
这是我发现使用组合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
Run Code Online (Sandbox Code Playgroud)
Joe*_*per 11
所以我最近遇到了这个问题,如果您不确定列是否存在并且只想重命名那些:
existing <- match(oldNames,names(x))
names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
Run Code Online (Sandbox Code Playgroud)
您可以使用命名向量。下面两个选项(带有基本 R 和 dplyr)。
基 R,通过子集化:
x = data.frame(q = 1, w = 2, e = 3)
rename_vec <- c(q = "A", e = "B")
## vector of same length as names(x) which returns NA if there is no match to names(x)
which_rename <- rename_vec[names(x)]
## simple ifelse where names(x) will be renamed for every non-NA
names(x) <- ifelse(is.na(which_rename), names(x), which_rename)
x
#> A w B
#> 1 1 2 3
Run Code Online (Sandbox Code Playgroud)
或者一个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
Run Code Online (Sandbox Code Playgroud)
后者之所以有效,是因为“大爆炸”运算!!!符强制评估列表或向量。
?`!!`
!!! 强制拼接对象列表。列表的元素被拼接到位,这意味着它们每个都成为一个参数。
names(x)[names(x) %in% c("q","e")]<-c("A","B")
Run Code Online (Sandbox Code Playgroud)
建立在@ 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
Run Code Online (Sandbox Code Playgroud)
这不依赖于x数据集中列的特定顺序.
dplyr::rename_with已经有一些答案提到了这些功能rlang::set_names。他们是分开的。这个答案说明了两者之间的差异以及使用函数和公式来重命名列。
rename_with从dplyr包中可以使用函数或公式来重命名作为.cols参数给出的所选列。例如传递函数名称toupper:
library(dplyr)
rename_with(head(iris), toupper, starts_with("Petal"))
Run Code Online (Sandbox Code Playgroud)
相当于传递公式~ toupper(.x):
rename_with(head(iris), ~ toupper(.x), starts_with("Petal"))
Run Code Online (Sandbox Code Playgroud)
重命名所有列时,您还可以使用set_namesrlang 包中的内容。为了制作一个不同的示例,让我们使用paste0重命名函数。pasteO接受 2 个参数,因此根据我们使用的是函数还是公式,有不同的方法来传递第二个参数。
rlang::set_names(head(iris), paste0, "_hi")
rlang::set_names(head(iris), ~ paste0(.x, "_hi"))
Run Code Online (Sandbox Code Playgroud)
rename_with通过将数据帧作为第一个参数.data、函数作为第二个参数.fn、所有列作为第三个参数.cols=everything()、函数参数作为第四个参数来实现相同的效果...。或者,您可以将第二个、第三个和第四个参数放入作为第二个参数给出的公式中。
rename_with(head(iris), paste0, everything(), "_hi")
rename_with(head(iris), ~ paste0(.x, "_hi"))
Run Code Online (Sandbox Code Playgroud)
rename_with仅适用于数据框。set_names更通用,还可以进行向量重命名
rlang::set_names(1:4, c("a", "b", "c", "d"))
Run Code Online (Sandbox Code Playgroud)