使用grep或grepl通过非完全匹配合并数据框?

时间:2016-05-25 10:32:07

标签: r merge grep grepl

我尽力找到答案,虽然我发现了'某事'但没有真正解决我的想法。至少,我是这么认为的,因为我对R和编程都是新手。任何帮助将不胜感激,请。

首先,'简单'场景。 我有一个data.frame ut ,其中包含商业供应商列表:

ut <- data.frame("supplier"=c("Aur","Chem", "Ena", "Inter","Ukr"))

我有供应商排名的参考数据。框架 rt

rt <- data.frame("supplier"=c("Aur","Chem", "Ena", "Inter"),"rank"=1:4)

如果我想用 rt 的等级填写 ut ,我知道我可以使用merge

> merge(ut,rt,all.x=TRUE,sort=FALSE)
  supplier rank
1      Aur    1
2     Chem    2
3      Ena    3
4    Inter    4
5      Ukr   NA

不幸的是,我得到的不是 ut ,而是 ut1 ,其中供应商名称最初由用户输入,因此它们通常比引用名称长,自由使用大写/小写,并不总是以引用名称中的字母开头。像这样:

ut1 <- data.frame("supplier"=c("Auro","chemD", "Enam", "SIA Enam", "interB","Ukror"))

merge在这里不起作用,因为没有完全匹配。 matchpmatch也不会。我想重现一个人在这种情况下会做什么:阅读 ut1 中的每一行,确定 rt 中的哪个供应商给出'最佳'匹配并记下相应的排名。 rt 汇总在一起,因此其供应商级别均不是任何其他级别的子字符串。因此 rt 中永远不会有“Ena”和“Enam”。 rt 中的供应商级别始终是供应商的最短可能的明确标识符,并且是互斥的。

我尝试了很多方法来完成这项工作。没有愚蠢循环似乎效果最好的那个是sapply,其中grepl为函数:

> sapply(rt$supplier, grepl, ut1$supplier, ignore.case=TRUE)
      [,1]  [,2]  [,3]  [,4]
[1,]  TRUE FALSE FALSE FALSE
[2,] FALSE  TRUE FALSE FALSE
[3,] FALSE FALSE  TRUE FALSE
[4,] FALSE FALSE  TRUE FALSE
[5,] FALSE FALSE FALSE  TRUE
[6,] FALSE FALSE FALSE FALSE

在这种情况下,每行有一个TRUE。情况不一定如此。例如。我可以在 ut1 中的一个供应商级别拥有“Ena Chem”。我很乐意在每一行中保留第一次出现的TRUE(有点像match,我相信),但我不知道如何。任何的想法?我尝试在上面的表达式中使用grep而不是grepl,但在某些情况下,这会给我一个向量,在其他情况下给出一个向量列表。

但是,假设我每行只有一个TRUE。上面矩阵的点积由 rt 的行号给出了行号 rt 的向量,其中有关 ut1 <中相应供应商的信息/ strong>包含在内:

> (sapply(rt$supplier, grepl, ut1$supplier,ignore.case=TRUE) %*% 1:dim(rt)[1])[,1]
[1] 1 2 3 3 4 0

我以为我拥有它:我只需要在 ut1 中创建一个新列,使用此向量从 rt 中提取信息。这是发生的事情(在将上述向量分配给 vr 之后):

> ut1["rank"] <- rt$rank[vr]
Error in `[<-.data.frame`(`*tmp*`, "rank", value = c(1L, 2L, 3L, 3L, 4L : 
  replacement has 5 rows, data has 6

所以这是我需要解决的第二个问题。从理论上讲,我可以在 ut1 中创建一列 rt 的行号:

> ut1["RN"] <- vr
> ut1
  supplier RN
1     Auro  1
2    chemD  2
3     Enam  3
4 SIA Enam  3
5   interB  4
6    Ukror  0

并用它来填写信息:

> ut1[ut1$RN!=0,"rank"] <- rt[vr,"rank"]
> ut1
  supplier RN rank
1     Auro  1    1
2    chemD  2    2
3     Enam  3    3
4 SIA Enam  3    3
5   interB  4    4
6    Ukror  0   NA

这对我来说非常麻烦。

你认为可以更高效/更优雅地完成吗?

谢谢!

0 个答案:

没有答案