【问题标题】:Selecting columns based on matching/fuzzy matching value of two columns根据两列的匹配/模糊匹配值选择列
【发布时间】:2016-07-28 06:51:44
【问题描述】:

我有数据框df1 与列"Year""Agent"

df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv", "suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"), c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent"), row.names = c(NA, -3L), class = "data.frame")

#df1
Year                                   Agent
1999   abn-amro-nv, suntrust banks, wachovia
1999                  jp morgan, abn-amro-nv
1998                ba-corp, boston bks, nbd

我有另一个数据框df2,它有5列"Rank""Arrangers""Share""Issues""Year",如下所示:

df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank", "suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L, 3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger", "Share", "Issues", "Year"), class = "data.frame", row.names = c(NA, -3L))

#df2
Rank    Arranger         Share    Issues    Year
 1      jp morgan        1.2       7        1999
 2      boston-bank      1.8       4        1998
 3      suntrust bk      2.1       3        1999

我需要将df1"Agent""Year"df2"Arranger""Year" 匹配,并从df2 中选择3 列,例如"Rank"、@9876543445@、@9876 @。 "Agent"df1"Arranger"df2 的匹配将是模糊匹配。这是因为它们并不完全相同。

我的原始数据框非常大,仅供参考。

以下是我的代码:

library(stringdist)

leadrep <- matrix(ncol=3, nrow=length(df1$Agent))

for (i in 1:length(df1$Agent)) {

  for (j in 1:length(df2$Arrangers)) {

      if ((ain(df2$Arrangers[j], df1$Agent[[i]], maxDist=0.3, 
      method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){             

         leadrep[i,] <-  df2[j, c('Rank', 'Mkt.Share', 'NumberofIssues')]

      }

  }
} 

在代码中,leadrep 是我创建的矩阵。这样我就可以填写for loop。我使用stringdist 包和ain 函数进行模糊匹配。我使用了两个for loopif 来比较字符串和年份。

上述代码有效,但由于我的数据框很大,因此需要很长时间才能获得结果。我真的认为我上面的方法不是有效的。如果有人为我现有代码提供更好的替代方案,那将是一个很大的帮助。

感谢您的所有帮助。

【问题讨论】:

  • 你遇到了什么错误?
  • Error: unexpected '&amp;' in: " if ((ain(df2$Arrangers[j], df1$Agent[[i]], maxDist=0.3, method="jw")) == 'TRUE') &amp;" 错误:“}”中出现意外的“}”
  • 这个问题可能会因为有一个额外的( 的简单错字而被关闭。
  • 如我所见,if中的“&”之前有3个左括号和3个右括号。额外的在哪里(?。
  • @sayaa 代码需要很长时间才能获得结果。我不认为这是获得结果的有效代码/方法。也许我应该编辑我的问题并请求一个更好的替代我现有方法的方法。

标签: r record-linkage


【解决方案1】:

以下方法使用foreach 而不是您的两个嵌套for 循环,这将使您在大型数据帧上的计算速度更快。请参阅 this 以了解该软件包的概述。你还应该看看这些小插曲。

library(foreach)
library(stringdist)

match.cond <- function(ij, df1, df2) {                                   ## 1.
  i = floor((ij-1) / nrow(df2)) + 1
  j = ij - (i-1) * nrow(df2)
  if ((ain(df2$Arranger[j], df1$Agent[[i]], maxDist=0.3, 
       method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){
    return(df2[j, c('Rank', 'Share', 'Issues')])
  }
}

leadrep <- foreach(ij = 1:(nrow(df1)*nrow(df2)), .combine=rbind) %do%    ## 2.
  match.cond(ij, df1, df2)

注意事项:

  1. match.cond 是封装到 kernel 函数中的匹配条件,foreach 将对来自 df1df2 的所有行对进行 矢量化。它的输入是ij,它是配对和两个数据帧的索引。在match.cond 内:
    • ij 转换为行索引 i 用于 df1j 用于 df2
    • 评估您的条件,如果满足条件,
    • 返回匹配行的df2 中的列。
  2. 这是foreach 电话。
    • 我们将索引ij1 循环到nrow(df1)*nrow(df2),它枚举了来自df1df2%do% 的所有行对match.cond 函数。请注意,这都是一行。
    • .combine=rbind 参数表明我们希望从match.cond 收集所有结果并将它们绑定为行。
    • 这将返回数据框leadrep

我已经测试了你的数据,我已经dput

df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv", 
"suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"), 
c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent"
), row.names = c(NA, -3L), class = "data.frame")

df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank", 
"suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L, 
3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger", 
"Share", "Issues", "Year"), class = "data.frame", row.names = c(NA, 
-3L))

这给了我想要的结果:

print(leadrep)
##   Rank Share Issues
##3     3   2.1      3
##2     1   1.2      7
##21    2   1.8      4

希望这会有所帮助。

【讨论】:

  • 感谢您的解决方案。我当前的代码花费了太多时间。所以你的方法可以帮助我减少计算时间。再次感谢。
  • 其实我的原帖有一点小错误。在计算ij 时,我应该使用now(df2) 而不是now(df1)。如果它们不相同,这将很重要,而测试数据并非如此。我已经对帖子进行了编辑。
猜你喜欢
  • 1970-01-01
  • 2022-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 1970-01-01
  • 2022-12-24
相关资源
最近更新 更多