【问题标题】:Joining two dataframes with messy column names in R在R中加入两个列名混乱的数据框
【发布时间】:2018-01-08 19:50:53
【问题描述】:

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

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

codes 是描述测量站的数据对象。
dataset1dataset2 是来自一些具有混乱列命名的站的测量 - 没有实际模式,除了“station#”部分.

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)

我确实觉得,dplyrjoins 和一些与 RegEx 匹配的字符串可以让我到达那里,但我被卡住了(几乎每次涉及 RegEx 时都会发生这种情况)。

编辑:在阅读Jennifer 答案后,我修改了我的示例代码以匹配更一般的情况,其中codes 数据帧中的ids 不一定由粘贴到station 的唯一编号标识,但可以实际上仅由字符串表示。

【问题讨论】:

  • newData 也更新了吗?
  • 我不确定我是否理解。 newData 行与dataset 行相同。 newData 列有名称,从匹配的id 映射到 codes。不匹配的列保留其原始名称

标签: r regex dplyr


【解决方案1】:

这是一个非常笨拙的解决方案。我确信有一种更漂亮的方法可以消除循环,但这至少可以让你到达你想去的地方。

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

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)

【讨论】:

  • Jennifer:这给了我仅以数字命名的列。在dataset1 我得到列:14 而我期待station1 station4 - 或者来自codes 的代码是什么。此外,当 station1 被称为 stationOne 时,此函数会失败。这里的目标是匹配codes 中的任何代码。无论如何感谢您的帮助:)
  • 我不知道为什么你会得到 1 和 4。我得到了 station1 和 station4。确保函数中的 code 参数设置为您要用于重命名的变量 - 在您的示例代码中为 id。你是对的。它只适用于 codes 表中的任何内容。 stationOnestation1 不是同一个字符串,所以它会中断。您可以先尝试使用gsub() 将书面数字更改为数字。
  • 现在我明白了,我已经把我的例子简化得太多了……codes 对象中的id 列实际上只能由字符串组成。虽然您的解决方案适用于编号 ID,但我认为我需要一种更通用的方法。在我的示例中,我仅使用数字来识别电台,因为它更容易输入 - 这是我的错误
【解决方案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)

【讨论】:

  • 谢谢!实际上只有gsub(...) 部分就足够了。我刚刚在真实数据上进行了测试,它可以满足我的需要。显然gsub 和正则表达式是我必须重新学习并最终学习的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-28
相关资源
最近更新 更多