我有一个大数据框df
,如下所示:
firstname = c("John L", "Robert C", "John", "J L", "Tom F", "T F", "Tom")
lastname = c("Doe", "Doe", "Doe", "Doe", "Frost", "Frost", "Frost")
id = c(178, 649, 384, 479, 539, 261, 347)
df = data.frame(firstname, lastname, id)
在df
视图中显示如下:
firstname lastname id
John L Doe 178
Robert C Doe 649
John Doe 384
J L Doe 479
Tom F Frost 539
T F Frost 261
Tom Frost 347
如您所见,数据框中的名字不一致。有时它只是一个例子。我想拥有一致的名字。我想有一个像这样的输出数据框:
firstname lastname id
John L Doe 178
Robert C Doe 649
John L Doe 384
John L Doe 479
Tom F Frost 539
Tom F Frost 261
Tom F Frost 347
我尝试了一些方法,比如使用lastname进行分组,然后为每个组获取最长的字符串,然后通过使用下面的组中的其他名字匹配来更新if elseif语句中的firstname
> sapply(strsplit("John L Doe"," "), function(a) paste(a[1],a[3]))
[1] "John Doe"
> sapply(strsplit("John L Doe"," "), function(a) paste(substr(a[1],1,1),a[2],a[3]))
[1] "J L Doe"
它没有用,因为我意识到在组中使用最长的字符串并不是一个好方法。
非常感谢先进的任何支持,以及解决此问题的指南。
编辑:为问题添加更多信息。
从firstname
的首字母到firstname
的完整形式的映射始终是正确的。例如,将会有" John L Doe"。但是,他的firstname
将有3个变种。例如," John L"," John"和" J L"。这是因为这些是非常狭窄主题的作者名单。我希望修复的名称格式只是不一致。拥有一个一致的名称将有助于我进行更广泛的分析。所以,我期待R
中的解决方案能够做到这一点。
答案 0 :(得分:1)
您尝试实现的目标通常是使用将每个拼写变体与首选名称相匹配的字典来完成。有基于文本相似性和文本挖掘的智能解决方案。除非你已经将字典c(" JL",J L",JL"等等......)链接到John L.我不会在R中这样做。 / p>
查看DataWrangler,Trifacta,Dataiku或Openrefine他们都有免费版本,可以满足您的需求。我知道Openrefine(以前是GoogleRefine)可以编写脚本。
答案 1 :(得分:1)
您的用例并不完全清楚。 如上所述,如果您的姓氏相同,初始名称相同但名字不同,则会出现问题。如果您确信在您的数据中绝不会出现这种情况,那么解决方案可能非常简单。
但是,如果你要做的是查明这些名字是否指的是同一个人,那么你需要更多,这意味着潜入实体的主题和解强>
这里有一些简洁的R套餐(我已经参与了涉及实体对账的项目),包括dd
,但最重要的是:如果你想要可靠的记录链接,你就可以了需要至少比名字更多一点&姓氏
答案 2 :(得分:1)
以下解决方案会产生您的预期结果,但请记住,如果Jack L Doe和John L Doe存在,J L Doe将映射到第一个最长的名称。
firstname = c("John L", "Robert C", "John", "J L", "Tom F", "T F", "Tom", "Jack L", "Robert Can","R C", "R C")
lastname = c("Doe", "Doe", "Doe", "Doe", "Frost", "Frost", "Frost", "Doe","Frost","Doe", "Frost")
id = c(178, 649, 384, 479, 539, 261, 347,100,200,300,400)
df = data.frame(firstname, lastname, id,stringsAsFactors = FALSE)
df$Initials <- sapply(strsplit(as.vector(firstname), " "), function(x) paste(substr(x, 1,1), collapse=""))
df$LongName<-apply(df,1,function(x) {
if(sub("\\s","",x[["firstname"]]) == x[["Initials"]]){
choices<-df$firstname[ grepl(x[["Initials"]], df$Initials) & df$lastname == x[["lastname"]]]
}
else{
choices<-df$firstname[ grepl(x[["Initials"]], df$Initials) & grepl(x[["firstname"]], df$firstname) & df$lastname == x[["lastname"]]]
}
choices[which.max(nchar(choices))]
}
)
结果
> df
firstname lastname id Initials LongName
1 John L Doe 178 JL John L
2 Robert C Doe 649 RC Robert C
3 John Doe 384 J John L
4 J L Doe 479 JL John L
5 Tom F Frost 539 TF Tom F
6 T F Frost 261 TF Tom F
7 Tom Frost 347 T Tom F
8 Jack L Doe 100 JL Jack L
9 Robert Can Frost 200 RC Robert Can
10 R C Doe 300 RC Robert C
11 R C Frost 400 RC Robert Can