在R中加入两个带有凌乱列名的数据帧

时间:2018-01-08 19:50:53

标签: r regex dplyr

鉴于这些示例性数据集(1和2):

如何合并每个数据集(1和2) 使用codes数据集,以便将名称codes$id映射(同步?)到colnames dataset1dataset2匹配的地方。

codes是描述测量站的数据对象 dataset1dataset2是来自某些站点的测量结果,这些站点具有混乱的列命名 - 除了“站#”部分之外没有实际模式。

codes<- data.frame(
      id=c("MotherStation", "station2", "station3",
           "station4", "stationFive", "station6"),
      id2=c("a", "b", "c", "d", "e", "f"),
      var1= seq(1:6),
      var2= seq(1:6))

dataset1 <- data.frame("291_hhaMotherStation_1g44" = rnorm(6), 
                        "143_wwaStation4_1d21"=rnorm(6))

dataset2 <- data.frame("143_wwaStation4_1d21" = rnorm(6), 
                        "station2WWa" = rnorm(6), 
                        "KrkStation6"=rnorm(6))

我正在寻找的结果是:

newData1 <- data.frame(MotherStation = dataset1$X291_hhaMotherStation_1g44,
                       station4 = dataset1$X143_wwaStation4_1d21)

newData2 <- data.frame(station4 = dataset2$X143_wwaStation4_1d21,
                       station2 = dataset2$station2WWa,
                       station6 = dataset2$KrkStation6)

我确实认为,dplyr join和一些与RegEx匹配的字符串可以让我在那里,但我被卡住了(几乎每次涉及RegEx时都会发生这种情况)。< / p>

编辑:在阅读Jennifer回答后,我修改了我的示例代码以匹配更一般的情况,id数据框中的codes s不一定由粘贴到的唯一编号标识station,但实际上只能用字符串表示。

2 个答案:

答案 0 :(得分:3)

这是一个非常复杂的解决方案。我确信有一个更漂亮的方法来消除循环,但这应该可以让你到达目的地,至少。

这标准化了两个数据集的名称。

rename_col <- function(code, dataset){
  index <- grep(code, names(dataset), ignore.case = TRUE)
  names(dataset)[index] <- code
  return(dataset)
}

for(i in seq_len(nrow(codes))){
  dataset1 <- rename_col(codes[i, "id"], dataset1)
  dataset2 <- rename_col(codes[i, "id"], dataset2)
}

从那里,您应该能够完全加入。

full_join(dataset1, dataset2)

答案 1 :(得分:2)

这应该有效 - 首先将不在id列中的所有内容分出来,然后用完全字符串替换它(因为大写/小写是不规则的)

dfs <- list(dataset1, dataset2)


out <-  lapply(dfs, function(x) {
  colnames(x) <- gsub(paste(".*(", paste(codes$id, collapse = "|"), ").*", sep = ""), 
       "\\1", colnames(x), perl = TRUE, ignore.case = TRUE)
  colnames(x) <- sapply(colnames(x), function(y) as.character(codes$id[tolower(codes$id) == tolower(y)]))
  return(x)
})

> all.equal(out[[1]], newData1)
[1] TRUE
> all.equal(out[[2]], newData2)
[1] TRUE

加入:

library(tidyverse)
do.call(full_join, out)