【发布时间】:2018-06-11 23:45:38
【问题描述】:
设置: 我有有关人员及其父母姓名的数据,我想找到兄弟姐妹(父母姓名相同的人)。
pdata<-data.frame(parents_name=c("peter pan + marta steward",
"pieter pan + marta steward",
"armin dolgner + jane johanna dough",
"jack jackson + sombody else"))
此处的预期输出将是一列,表明前两个观测值属于 X 族,而第三列和第四列分别属于一个单独的族。例如:
person_id parents_name family_id
1 "peter pan + marta steward", 1
2 "pieter pan + marta steward", 1
3 "armin dolgner + jane johanna dough", 2
4 "jack jackson + sombody else" 3
目前的做法: 我对距离度量很灵活。目前,我使用 Levenshtein 编辑距离来匹配 obs,允许两个字符的差异。但是其他变体,例如“最大公共子字符串”,如果它们运行得更快,那就没问题了。
对于较小的子样本,我在循环中使用 stringdist::stringdist 或 stringdist::stringdistmatrix,但随着样本量的增加,效率会越来越低。
一旦使用一定的样本量,矩阵版本就会爆炸。我非常低效的循环尝试在这里:
#create data of the same complexity using random last-names
#(4mio obs and ~1-3 kids per parents)
pdata<-data.frame(parents_name=paste0(rep(c("peter pan + marta ",
"pieter pan + marta ",
"armin dolgner + jane johanna ",
"jack jackson + sombody "),1e6),stringi::stri_rand_strings(4e6, 5)))
for (i in 1:nrow(pdata)) {
similar_fatersname0<-stringdist::stringdist(pdata$parents_name[i],pdata$parents_name[i:nrow(pdata)],nthread=4)<2
#[create grouping indicator]
}
我的问题:应该有显着的效率提升,例如因为一旦我发现它们在更容易评估的东西上存在很大差异,我就可以停止比较字符串,例如。字符串长度,或第一个单词。字符串长度变体已经起作用,并将复杂性降低了约 3 倍。但这远远太少了。任何减少计算时间的建议都值得赞赏。
备注:
- 字符串实际上是 unicode,而不是拉丁字母 (Devnagari)
- 已完成删除未使用字符等的预处理
【问题讨论】:
-
您的 for 循环不工作。此外,您应该提供您正在使用的规模的示例数据...
-
希望您明白,出于保密原因,我无法提供实际数据
-
问题:检查
pdata$parents_name[1:i]的距离不是更好吗?第一项将始终是它自己的family_id(因为尚未分配其他家庭ID)。那么第二个项目只需要与第一个项目进行比较,因为其他项目都没有分配family_id。 -
如果这些示例与您的实际情况足够接近,您可能不需要计算所有成对距离,如果它们之间的距离小于 4,您可能会认为 2 个字符串具有相同的 family_id,并且将 family_id 的第一个实例视为规范实例,如果您有相当数量的 family_id 实例,它会快得多。对值得计算的距离进行额外的预过滤可以通过拆分“+”并消除长度非常不同的对(比如超过 3 个字符)来完成。
标签: r string performance levenshtein-distance