2017-03-07 58 views
0

我有一個大的數據幀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 

我試圖像由姓分組,然後讓最長的字符串爲每個組,然後更新姓名的幾種方法中,如果通過與其他姓名匹配ELSEIF聲明使用以下

> 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的解決方案來做到這一點。

+1

在您的實際問題的背景下,如何你就會知道,約翰和約翰大號指的是同一個人?如果我有Jack L Doe,J L Doe會映射到誰? – Jean

+0

是否有人姓氏相同,如果你匹配首字母縮寫以轉換爲長格式,你知道他們正在映射到正確的人嗎?編輯說,@沃特林更清楚地表達了我的擔憂。 – Djork

+0

@waterling我的數據框很窄。所以,無論何時,例如,J L Doe都會映射到John L Doe,而不是Jack L Doe – Santosh

回答

1

以下解決方案會產生您的預期結果,但請記住,如果Jack L Doe和John L Doe存在,JL 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 
1

您試圖實現的目標通常是通過將每個拼寫變體匹配到首選名稱的字典完成的。有基於文本相似性和文本挖掘的智能解決方案。除非你已經有字典連接C(「JL」,JL「,JL」等....)到約翰L.我不會這樣做在R.

看看DataWrangler,TrifactaDataikuOpenrefine他們都有一個免費版本,將做你正在尋找。我知道Openrefine(之前是GoogleRefine)可以編寫腳本。

1

您的用例不完全清楚。 如上所述,如果您的姓氏相同,姓名相同但姓名不同,則會出現問題。如果您確信數據中永遠不會出現這種情況,那麼解決方案可能非常簡單。

但是,如果您要做的是找出名稱是否指向同一個人,那麼您將需要更多,這意味着要深入到實體調節的主題。

這裏有一些整潔的R包(我曾參與一個涉及實體對帳的項目),其中包括RecordLinkage,但底線是:如果您想要可靠的記錄鏈接,至少需要一點點名字&姓氏

+0

映射將始終是正確的。這是因爲名字和姓氏的列表集中在非常狹窄的主題上。我知道解決方案可能是非常簡單的R代碼。 – Santosh