R 数据框中每个组的字符串更新

R 数据框中每个组的字符串更新,r,R,我有一个大数据帧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) firs

我有一个大数据帧
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)
 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
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 = 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)
 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分组,然后获取每个组的最长字符串,然后使用下面的方法通过与组中的其他firstname匹配来更新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" 
它不起作用,因为我意识到在小组中使用最长的字符串不是一个好方法

非常感谢advanced中的支持,以及解决此问题的指南

编辑:向问题添加更多信息


firstname
的首字母缩写到
firstname
的完整形式的映射总是正确的。例如,将出现“约翰·多伊”。但是,他的名字将有3个变体。例如,“John L”、“John”和“J L”。这是因为这些都是关于非常狭窄主题的作者名单。有一个只是在名称的格式不一致,我想修复。有一个一致的名字将有助于我在更大范围内做更多的分析。因此,我希望
R
中的解决方案能够做到这一点

你想要达到的目的通常是通过一本字典将每个拼写变体匹配到一个首选名称。有基于文本相似性和文本挖掘的智能解决方案。除非你已经有了把c(“JL”,JL,J.L.”等链接到John L的字典,否则我不会用R


看一看,或者他们都有一个免费的版本,可以满足你的需求。我知道Openrefine(以前是GoogleRefine)是可以编写脚本的。

您要实现的目标通常是使用字典将每个拼写变体匹配到首选名称。有基于文本相似性和文本挖掘的智能解决方案。除非你已经有了把c(“JL”,JL,J.L.”等链接到John L的字典,否则我不会用R


看一看,或者他们都有一个免费的版本,可以满足你的需求。我知道Openrefine(以前是GoogleRefine)可以编写脚本。

您的用例并不完全清楚。 如前所述,如果您有相同姓氏、相同首字母但不同名字的人,则会出现问题。如果您确信数据中永远不会出现这种情况,那么解决方案可能非常简单

但是,如果您想知道这些名字是否指的是同一个人,那么您需要更多,这意味着要深入研究实体对账的主题


有一些整洁的R包(我参与了一个涉及实体对账的项目)包括
记录链接
,但底线是:如果你想要可靠的记录链接,你至少需要比名字和姓氏多一点你的用例并不完全清楚。 如前所述,如果您有相同姓氏、相同首字母但不同名字的人,则会出现问题。如果您确信数据中永远不会出现这种情况,那么解决方案可能非常简单

但是,如果您想知道这些名字是否指的是同一个人,那么您需要更多,这意味着要深入研究实体对账的主题


有一些整洁的R包(我参与了一个涉及实体对账的项目)包括
记录链接
,但底线是:如果你想要可靠的记录链接,你至少需要比名字和姓氏多一点以下解决方案产生你的预期结果,但请记住,如果杰克·多伊和约翰·多伊存在,那么J·L·多伊将映射到第一个最长的名字

  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))]
    }
  )

下面的解决方案会产生您预期的结果,但请记住,如果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))]
    }
  )

在你现实问题的背景下,你怎么知道John和John L指的是同一个人?如果我有一个Jack L Doe,J L Doe会映射到谁?有没有姓相同的人?如果你匹配名字的首字母缩写以转换为长格式,你知道他们映射到的是正确的人吗?编辑后说@waterling更清楚地表达了我的担忧。@waterling我的数据框在手头的主题上很窄。所以,一直以来,例如,J L Doe都会映射到John L Doe,而不是Jack LDoe@R.S.有些人姓相同。这就是为什么我要举一个例子。当我匹配名字的首字母以转换为长形式时,它们映射到正确的人。在现实问题的背景下,你怎么知道John和John L指的是同一个人?如果我有一个Jack L Doe,J L Doe会映射到谁?有没有姓相同的人?如果你匹配名字的首字母缩写以转换为长格式,你知道他们映射到的是正确的人吗?编辑后说@waterling更清楚地表达了我的担忧。@waterling我的数据框在手头的主题上很窄。所以,一直以来,例如,J L Doe都会映射到John L Doe,而不是Jack LDoe@R.S.有些人姓相同。这就是为什么我要举一个例子。当我匹配要转换为长格式的名字的首字母时,它们映射到正确的人。映射将始终正确。这是因为名字和姓氏的列表集中在非常狭窄的主题上。我知道解决方案可能是非常简单的R代码。映射将始终正确。这是因为名字和姓氏的列表集中在非常狭窄的主题上。我知道解决方案可能是非常简单的R代码。