r - 连接多个数据框时使用数据框名称作为后缀

标签 r join dplyr

我需要合并多个具有重复列名的数据框。我使用 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/

相关文章:

r - R中故障率和日期时间操作的计算

使用查找表使用 dpylr 重新编码值

python - 升级到 OSX El Capitan 后出现 rpy2 错误

r - ggplot2 - 一个分面图不显示 stat_compare_means Kruskal

sql - 如何修改此 SQL 连接以包含所有列?

sql-server - 为什么这次加入需要这么长时间?

sql - 来自 3 个相关表的 MySQL JOIN

r - 条件滚动平均值

r - 如何从 dplyr 中的 case_when 捕获逻辑

r - 在 Shiny 服务器启动时触发 selectInput 的 Shiny R observeEvent