将data.frame中的多个列连接到引用data.frame中的单个列

时间:2017-12-12 05:17:26

标签: r dplyr left-join

我正在尝试加入两个数据帧。然而,与普通连接不同,我想匹配第一个和第二个列的一系列列。 基本上我有一个网站列表,其中提到了最近的周边网站。我需要在一个单独的数据框中查找最近的站点全Gauge和LTA ID。我提供了一些示例数据帧,包括一个示例输出,但真实的东西几乎不是这么整齐(并且有更多的列和行)这就是为什么我需要在{{Surrogate量表中查找1}},而不是在下面的方法中创建。

TestRefList

我以为我可以使用plyr :: ldply和dplyr :: left_join的某些组合,例如:     Out< - ldply(姓名(代理人)[2:3],                           function(x)left_join(代理,TestRefList,by = c(paste0(x,'=“Site”'))))

但是我无法使用列表中的名称加入工作。我已经在列表之外尝试了一些“等于”的安排,例如:

library(plyr)
library(tidyverse)

TestRefList <- data.frame(Site = paste0("sl",1:10,".1"), Gauge = paste0(1:10,".1","/110.00/1"), LTA = paste0(1:10,".1","/110.99/1"), stringsAsFactors = F)
Surrogates <- data.frame(Primary = paste0("sl",c(2,4,6),".1"), nearest1=paste0("sl",1:3,".1"), nearest2=paste0("sl",7:9,".1"), stringsAsFactors = F)
HopefulOutput <- data.frame(Primary = paste0("sl",c(2,4,6),".1"), nearest1=paste0("sl",1:3,".1"), nearest2=paste0("sl",7:9,".1"), 
                    nearest1Gauge = paste0(1:3,".1","/110.00/1"), nearest1LTA = paste0(1:3,".1","/110.99/1"), 
                    nearest2Gauge = paste0(7:9,".1","/110.00/1"), nearest2LTA = paste0(7:9,".1","/110.99/1"), stringsAsFactors = F)

即使我能让这部分工作,我也不确定它在ldply中是如何工作的。

有什么想法吗?如果有必要的话,我很高兴能够采用完全不同的方式,尽管我比data.table选项更适合data.frames和tidyverse

3 个答案:

答案 0 :(得分:1)

我提供基于re的解决方案。当然,您可以根据要求使用data.table完成任务。但是,我不太清楚dplyr是否能够解决问题。另外,我认为下面的data.table解决方案非常优雅和快速,只要您愿意在工作流程中添加另一个包。此外,此代码已经适用于任何数量的&#34;最近的n&#34;数据中的列。

dplyr

答案 1 :(得分:0)

以下是Surrogates中任意数量的“最近”列的通用解决方案。它首先得到一个“最近”列的向量,然后从那里开始。

# get list of columns matching "nearest"
nearestCols <- colnames(Surrogates) %>%
  `[`(grepl("nearest", .))

# output data.frame
out <- Surrogates

# for each "nearest" column, merge Gauge and LTA
for (n in nearestCols) {
  out <- merge(out, TestRefList, by.x = n, by.y = "Site", all.x = TRUE)
  colnames(out)[(ncol(out)-1):ncol(out)] <- paste0(n, c("Gauge", "LTA"))
}

# re-order the columns
out <- out[, c(length(nearestCols) + 1, length(nearestCols):1, (length(nearestCols)+2):ncol(out))]

输出:

> out
  Primary nearest1 nearest2 nearest1Gauge  nearest1LTA nearest2Gauge  nearest2LTA
1   sl2.1    sl1.1    sl7.1  1.1/110.00/1 1.1/110.99/1  7.1/110.00/1 7.1/110.99/1
2   sl4.1    sl2.1    sl8.1  2.1/110.00/1 2.1/110.99/1  8.1/110.00/1 8.1/110.99/1
3   sl6.1    sl3.1    sl9.1  3.1/110.00/1 3.1/110.99/1  9.1/110.00/1 9.1/110.99/1
> identical(out, HopefulOutput)
[1] TRUE

答案 2 :(得分:0)

Reduce(function(x, fld) merge(x, TestRefList, by.x=fld, by.y="Site"),
       c("nearest1", "nearest2"), init = Surrogates)
#   nearest2 nearest1 Primary      Gauge.x        LTA.x      Gauge.y        LTA.y
# 1    sl7.1    sl1.1   sl2.1 1.1/110.00/1 1.1/110.99/1 7.1/110.00/1 7.1/110.99/1
# 2    sl8.1    sl2.1   sl4.1 2.1/110.00/1 2.1/110.99/1 8.1/110.00/1 8.1/110.99/1
# 3    sl9.1    sl3.1   sl6.1 3.1/110.00/1 3.1/110.99/1 9.1/110.00/1 9.1/110.99/1

您可以根据需要重命名列。这可以通过dplyr::left_join完成,但几乎没有变化:

Reduce(function(x, fld) left_join(x, TestRefList, by = setNames("Site", fld)),
       c("nearest1", "nearest2"), init = Surrogates)

或在管道中:

Surrogates %>% 
  Reduce(function(x, fld) left_join(x, TestRefList, by = setNames("Site", fld)),
         c("nearest1", "nearest2"), init = .)