我需要合并多个具有重复列名的数据框。我使用 dplyr::left_join 和 purrr::reduce 来迭代文件上的函数。 dplyr::left_join 的标准行为是为重复的列名称添加后缀,但这无助于找出变量来自哪些文件,除非您手头有代码。以下是我的情况的简化示例:
a <- tibble(id = 1:5, var=letters[1:5])
b <- tibble(var=letters[11:15], id=1:5)
c <- tibble(id = 1:5, var=letters[16:20], var2="a")
reduce(list(a,b,c), left_join, by="id")
# A tibble: 5 x 5
id var.x var.y var var2
<int> <chr> <chr> <chr> <chr>
1 1 a k p a
2 2 b l q a
3 3 c m r a
4 4 d n s a
5 5 e o t a
有没有办法使用数据框名称作为后缀,并强制后缀所有重复的列?我想要的是:
# A tibble: 5 x 5
id var.a var.b var.c var2
<int> <chr> <chr> <chr> <chr>
1 1 a k p a
2 2 b l q a
3 3 c m r a
4 4 d n s a
5 5 e o t a
left_join
中有一个 suffix
选项,但如何在 reduce
中使用它?
最佳答案
left_join 中的后缀无法工作,因为当一次仅作用于两个输入数据帧时,它不知道哪些列在所有输入数据帧中是唯一的或不是唯一的。
1) 相反,请在连接之前的所有数据帧中为所有非 by 列添加后缀。 left_join 行中的 by = "id"可以省略,因为它会默认为该值。
最后,我们删除了唯一出现的没有后缀的列上的后缀;但是,在这种情况下可能并不需要这样做,请省略 rmSuffix (删除任何后缀)和 uniq_stem (仅返回其向量参数中主干唯一的那些组件)以及管道末尾的 rename_with 行。
如果您不需要最终的 rename_with 及其使用的相关函数,那么这种方法可能没问题,因为它非常简单;否则,最好选择 (2) 以避免 (1) 中保留的某些边缘情况,以及在 left_join 之前设置列名称的丑陋之处,但必须在 left_join 之后再次修复它们。
library(dplyr)
library(purrr)
library(tibble)
rmSuffix <- function(x) sub("\\.[^.]*", "", x)
uniq_stem <- function(x) x[ave(x, rmSuffix(x), FUN = length) == 1]
lst(a, b, c) %>%
map2(names(.), ~ rename_with(.x, function(x) paste(x, .y, sep = "."), -id)) %>%
reduce(left_join, by = "id") %>%
rename_with(rmSuffix, .cols = uniq_stem(names(.)))
给予:
# A tibble: 5 x 5
id var.a var.b var.c var2
<int> <chr> <chr> <chr> <chr>
1 1 a k p a
2 2 b l q a
3 3 c m r a
4 4 d n s a
5 5 e o t a
2) 第二种方法是在 left_join 之前完全处理列表。这消除了与修复 (1) 中的初始重命名相关的所有正则表达式和问题。 add_suffix 有 data.frame 和 list 方法。在后一种情况下,列表必须是数据框的命名列表,并且排除是列名称的向量,除了列表的数据框中唯一出现的列名称之外,不为其添加后缀。
add_suffix <- function(x, ...) UseMethod("add_suffix")
add_suffix.data.frame <- function(x, suffix, exclude = NULL, ...) {
ok <- !names(x) %in% exclude
names(x)[ok] <- paste(names(x)[ok], suffix, sep = ".")
x
}
add_suffix.list <- function(x, exclude = NULL, ...) {
nms <- unlist(lapply(x, names))
exclude2 <- unname(c(nms[ave(nms, nms, FUN = length) == 1], exclude))
Map(add_suffix, x, names(x), MoreArgs = list(exclude = exclude2))
}
lst(a, b, c) %>%
add_suffix(exclude = "id") %>%
reduce(left_join, by = "id")
关于r - 连接多个数据框时使用数据框名称作为后缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66461873/