使用 dplyr 的 rename() 包括不在数据集中的变量名
Using dplyr's rename() including variable names not in data set
我正在尝试将一些 plyr 代码转换为 dplyr,并在 dplyr 中使用 rename() 的新功能。我希望能够为一组具有重叠但原始名称不同的数据集重用单个 rename() 表达式。例如,
sample1 <- data.frame(A=1:10, B=letters[1:10])
sample2 <- data.frame(B=11:20, C=letters[11:20])
然后,
rename(sample1, var1 = A, var2 = B, var3 = C)
我希望结果是变量 A 重命名为 var1,B 重命名为 var2,在这种情况下不添加 var3。相反,我得到
错误:未知变量:C.
相比之下,plyr 语法会让我使用
rename(sample1, c("A" = "var1", "B" = "var2", "C" = "var3"))
rename(sample2, c("A" = "var1", "B" = "var2", "C" = "var3"))
并且不会抛出错误。有没有办法在 dplyr 中获得相同的结果而不会出现未知变量错误?
#no need to use rename
oldnames<-unique(c(names(sample1),names(sample2)))
newnames<-c("var1","var2","var3")
name_df<-data.frame(oldnames,newnames)
mydata<-list(sample1,sample2) # combined two datasets as a list
#one liner
finaldata <- lapply(mydata, function(i) {colnames(i)<-name_df[name_df[,1] %in% colnames(i),2]
return(i)})
> finaldata
[[1]]
var1 var2
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
8 8 h
9 9 i
10 10 j
[[2]]
var2 var3
1 11 k
2 12 l
3 13 m
4 14 n
5 15 o
6 16 p
7 17 q
8 18 r
9 19 s
10 20 t
完全忽略您关于如何使用 dplyr 执行此操作的实际请求,我想建议使用查找的不同方法 table:
sample1 <- data.frame(A=1:10, B=letters[1:10])
sample2 <- data.frame(B=11:20, C=letters[11:20])
rename_map <- c("A"="var1",
"B"="var2",
"C"="var3")
names(sample1) <- rename_map[names(sample1)]
str(sample1)
names(sample2) <- rename_map[names(sample2)]
str(sample2)
基本上算法很简单:
- 构建查找 table 当前变量名称到所需名称
- 使用 names() 函数,使用映射索引查找映射并将这些映射变量分配给适当的列。
编辑:根据 Hadley 的建议,我使用命名向量而不是列表,让生活更轻松。我总是忘记命名向量:(
我以前用过 @earino 的答案
我自己,但发现它可能不安全。如果数据的列名
命名向量(的名称)中缺少框架,这些列名称被默默地替换为 NA
,这当然不是您想要的。
d1 <- data.frame(A = 1:10, B = letters[1:10], stringsAsFactors = FALSE)
rename_vec <- c("B" = "var2", "C" = "var3")
names(d1) <- rename_vec[names(d1)]
str(d1)
#> 'data.frame': 10 obs. of 2 variables:
#> $ NA : int 1 2 3 4 5 6 7 8 9 10
#> $ var2: chr "a" "b" "c" "d" ...
同样的事情也会发生,如果你 运行 names(d1) <- rename_vec[names(d1)]
两次是偶然的,因为当你 运行 第二次时, none
colnames(d1)
在 names(rename_vec)
.
names(d1) <- rename_vec[names(d1)]
str(d1)
#> 'data.frame': 10 obs. of 2 variables:
#> $ NA: int 1 2 3 4 5 6 7 8 9 10
#> $ NA: chr "a" "b" "c" "d" ...
我们只需要 select 重命名向量中数据框 和 中的那些列。
d2 <- data.frame(B1 = 1:10, B = letters[1:10], stringsAsFactors = FALSE)
sel <- is.element(colnames(d2), names(rename_vec))
names(d2)[sel] <- rename_vec[names(d2)][sel]
str(d2)
#> 'data.frame': 10 obs. of 2 variables:
#> $ B1 : int 1 2 3 4 5 6 7 8 9 10
#> $ var2: chr "a" "b" "c" "d" ...
更新:我最初在这里有一个涉及字符串替换的解决方案,结果证明它也不安全,因为它允许部分匹配。我觉得这个比较好
使用 dplyr
,我们可以使用一个命名向量,旧名称作为值,新名称作为名称,然后只取消引用 name_vec
中与数据集中的名称匹配的值。 rename
支持不加引号的字符,因此无需事先将它们转换为 sym
:
library(dplyr)
name_vec <- c(var1 = "A", var2 = "B", var3 = "C")
sample1 %>%
rename(!!name_vec[name_vec %in% names(.)])
sample2 %>%
rename(!!name_vec[name_vec %in% names(.)])
还有 setNames
:
name_vec <- c(A = "var1", B = "var2", C = "var3")
sample1 %>%
setNames(name_vec[names(.)])
sample2 %>%
setNames(name_vec[names(.)])
输出:
var1 var2
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
8 8 h
9 9 i
10 10 j
var2 var3
1 11 k
2 12 l
3 13 m
4 14 n
5 15 o
6 16 p
7 17 q
8 18 r
9 19 s
10 20 t
我正在尝试将一些 plyr 代码转换为 dplyr,并在 dplyr 中使用 rename() 的新功能。我希望能够为一组具有重叠但原始名称不同的数据集重用单个 rename() 表达式。例如,
sample1 <- data.frame(A=1:10, B=letters[1:10])
sample2 <- data.frame(B=11:20, C=letters[11:20])
然后,
rename(sample1, var1 = A, var2 = B, var3 = C)
我希望结果是变量 A 重命名为 var1,B 重命名为 var2,在这种情况下不添加 var3。相反,我得到
错误:未知变量:C.
相比之下,plyr 语法会让我使用
rename(sample1, c("A" = "var1", "B" = "var2", "C" = "var3"))
rename(sample2, c("A" = "var1", "B" = "var2", "C" = "var3"))
并且不会抛出错误。有没有办法在 dplyr 中获得相同的结果而不会出现未知变量错误?
#no need to use rename
oldnames<-unique(c(names(sample1),names(sample2)))
newnames<-c("var1","var2","var3")
name_df<-data.frame(oldnames,newnames)
mydata<-list(sample1,sample2) # combined two datasets as a list
#one liner
finaldata <- lapply(mydata, function(i) {colnames(i)<-name_df[name_df[,1] %in% colnames(i),2]
return(i)})
> finaldata
[[1]]
var1 var2
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
8 8 h
9 9 i
10 10 j
[[2]]
var2 var3
1 11 k
2 12 l
3 13 m
4 14 n
5 15 o
6 16 p
7 17 q
8 18 r
9 19 s
10 20 t
完全忽略您关于如何使用 dplyr 执行此操作的实际请求,我想建议使用查找的不同方法 table:
sample1 <- data.frame(A=1:10, B=letters[1:10])
sample2 <- data.frame(B=11:20, C=letters[11:20])
rename_map <- c("A"="var1",
"B"="var2",
"C"="var3")
names(sample1) <- rename_map[names(sample1)]
str(sample1)
names(sample2) <- rename_map[names(sample2)]
str(sample2)
基本上算法很简单:
- 构建查找 table 当前变量名称到所需名称
- 使用 names() 函数,使用映射索引查找映射并将这些映射变量分配给适当的列。
编辑:根据 Hadley 的建议,我使用命名向量而不是列表,让生活更轻松。我总是忘记命名向量:(
我以前用过 @earino 的答案
我自己,但发现它可能不安全。如果数据的列名
命名向量(的名称)中缺少框架,这些列名称被默默地替换为 NA
,这当然不是您想要的。
d1 <- data.frame(A = 1:10, B = letters[1:10], stringsAsFactors = FALSE)
rename_vec <- c("B" = "var2", "C" = "var3")
names(d1) <- rename_vec[names(d1)]
str(d1)
#> 'data.frame': 10 obs. of 2 variables:
#> $ NA : int 1 2 3 4 5 6 7 8 9 10
#> $ var2: chr "a" "b" "c" "d" ...
同样的事情也会发生,如果你 运行 names(d1) <- rename_vec[names(d1)]
两次是偶然的,因为当你 运行 第二次时, none
colnames(d1)
在 names(rename_vec)
.
names(d1) <- rename_vec[names(d1)]
str(d1)
#> 'data.frame': 10 obs. of 2 variables:
#> $ NA: int 1 2 3 4 5 6 7 8 9 10
#> $ NA: chr "a" "b" "c" "d" ...
我们只需要 select 重命名向量中数据框 和 中的那些列。
d2 <- data.frame(B1 = 1:10, B = letters[1:10], stringsAsFactors = FALSE)
sel <- is.element(colnames(d2), names(rename_vec))
names(d2)[sel] <- rename_vec[names(d2)][sel]
str(d2)
#> 'data.frame': 10 obs. of 2 variables:
#> $ B1 : int 1 2 3 4 5 6 7 8 9 10
#> $ var2: chr "a" "b" "c" "d" ...
更新:我最初在这里有一个涉及字符串替换的解决方案,结果证明它也不安全,因为它允许部分匹配。我觉得这个比较好
使用 dplyr
,我们可以使用一个命名向量,旧名称作为值,新名称作为名称,然后只取消引用 name_vec
中与数据集中的名称匹配的值。 rename
支持不加引号的字符,因此无需事先将它们转换为 sym
:
library(dplyr)
name_vec <- c(var1 = "A", var2 = "B", var3 = "C")
sample1 %>%
rename(!!name_vec[name_vec %in% names(.)])
sample2 %>%
rename(!!name_vec[name_vec %in% names(.)])
还有 setNames
:
name_vec <- c(A = "var1", B = "var2", C = "var3")
sample1 %>%
setNames(name_vec[names(.)])
sample2 %>%
setNames(name_vec[names(.)])
输出:
var1 var2
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e
6 6 f
7 7 g
8 8 h
9 9 i
10 10 j
var2 var3
1 11 k
2 12 l
3 13 m
4 14 n
5 15 o
6 16 p
7 17 q
8 18 r
9 19 s
10 20 t