我尽力找到答案,虽然我发现了'某事'但没有真正解决我的想法。至少,我是这么认为的,因为我对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
在这里不起作用,因为没有完全匹配。 match
或pmatch
也不会。我想重现一个人在这种情况下会做什么:阅读 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
这对我来说非常麻烦。
你认为可以更高效/更优雅地完成吗?
谢谢!