想法是比较两个字符串向量,例如:
df <- data.frame(a = c("New York 001","Orlando 002","Boston 003","Chicago 004","Atlanta 005"),b = c("NEW YORK 001","Orlando","Boston (003)","Chicago 005","005 Atlanta"))
并想出一种方法来给他们一些精确度.基本上添加具有数值的列c.
我的思路:
我们有这个:
> df a b 1 New York 001 NEW YORK 001 2 Orlando 002 Orlando 3 Boston 003 Boston (003) 4 Chicago 004 Chicago 005 5 Atlanta 005 005 Atlanta
第一件事是第一件事 – 剥离白人,忽略案件并删除所有特殊字符.
df$a <- gsub("[[:space:]]|[[:punct:]]","",toupper(df$a)) df$b <- gsub("[[:space:]]|[[:punct:]]",toupper(df$b))
我们得到了什么:
> df a b 1 NEWYORK001 NEWYORK001 2 ORLANDO002 ORLANDO 3 BOSTON003 BOSTON003 4 CHICAGO004 CHICAGO005 5 ATLANTA005 005ATLANTA
所以现在我们处于问题的核心.
第一行将是100%匹配.
第二行有7个匹配字符,最多10个字符.因此70%.
第三名现在比赛为100%.
第四名有90%的比赛.
第五个是棘手的.人类的头脑告诉我他们匹配,但订单有问题.但这不是计算机的工作原理.实际上它可以被测量为70%匹配,因为在两个字符串中重复7个连续字符.
所以问题是:
如何对字符串比较进行定量测量?
也许有一种更好的方法可以做到这一点,因为我从未有过比较部分匹配的字符串集的经验.并且采用这种特殊的可量化措施只是我直观的做事方式.
如果R已经有一个库/函数以更好的方式完成所有这些,我根本不知道,我不会感到惊讶.
解决方法
Rcpp更正确的答案:
library(Rcpp) cppFunction('NumericVector commonChars(CharacterVector x,CharacterVector y) { int len = x.size(); NumericVector out(len); double percentage; int count=0,k=0; std::string compared; std::string source; for (int i=0; i<len;++i) { source = x[i]; compared = y[i]; count=0; k=0; for (int j=0;j<compared.length();j++) { if (source[j] == compared[j]) { count++; continue; } while(k < source.length()) { if (source[j] == compared[k]) { count++; break; } k++; } } percentage = (count+0.0)/(source.length()+0.0); out[i] = percentage; } return out; }')
赠送:
> commonChars(df$a,df$b) [1] 1.0 0.7 1.0 0.9 0.7
我没有针对其他答案或大数据框架进行测试.
不是你真正想要的,但这是一个想法(我会尝试改进它):
df$r <- gsub("\\w","(\1)?",df$a) for (i in 1:length(df$a)) { df$percentage[i] < ( as.integer( attr( regexpr( df$r[i],df$b[i]),"match.length" ) ) / str_length(df$a[i]) * 100) }
输出:
a b r percentage 1 NEWYORK001 NEWYORK001 (N)?(E)?(W)?(Y)?(O)?(R)?(K)?(0)?(0)?(1)? 100 2 ORLANDO002 ORLANDO (O)?(R)?(L)?(A)?(N)?(D)?(O)?(0)?(0)?(2)? 70 3 BOSTON003 BOSTON003 (B)?(O)?(S)?(T)?(O)?(N)?(0)?(0)?(3)? 100 4 CHICAGO004 CHICAGO005 (C)?(H)?(I)?(C)?(A)?(G)?(O)?(0)?(0)?(4)? 90 5 ATLANTA005 005ATLANTA (A)?(T)?(L)?(A)?(N)?(T)?(A)?(0)?(0)?(5)? 30
缺点:
>有一个for循环
> ATLANTA005因为005仅在订单中匹配而返回30%.
我会看看我是否能找到一种方法来构建更好的正则表达式