2014-12-25 26 views
1

我試圖做什麼應該是R中數據框之間的簡單查找/更新沒有成功。它基於一些Flickr數據,其中一些相機具有許多不同的名稱 - 我想將它們中的每一個轉換爲標準名稱。我在這裏看到了類似的答案 - 但是他們似乎沒有處理匹配子字符串的情況,該子字符串可能出現在列的任何位置。使用來自另一個data.frame的查找值更新data.frame中的列 - 與子字符串匹配

我已經把一組簡化的數據在這裏的這說明我的問題:

LookupDF <- data.frame(Testr=c("EOS DIGITAL REBEL XTI   (EOS 400D, EOS KISS X)",  "PowerShot S400 (Digital IXUS 400, IXY Digital 400)", "PowerShot A530", "PowerShot A2300", "PowerShot A720 IS", "PowerShot SD880 IS (Digital IXUS 870 IS, IXY Digital 920 IS, IXY 999)")) 

小tidyup +創建一個新的列(我決定使用第一相機的名稱爲「標準名稱」) :

LookupDF$StandardName <- sapply(strsplit(as.character(LookupDF$Testr),'\\('), "[", 1) 
LookupDF$StandardName <- gsub("[[:space:]]*$","",LookupDF$StandardName) 
LookupDF 

                   Testr   StandardName 
1     EOS DIGITAL REBEL XTI   (EOS 400D, EOS KISS X) EOS DIGITAL REBEL XTI 
2     PowerShot S400 (Digital IXUS 400, IXY Digital 400)  PowerShot S400 
3              PowerShot A530  PowerShot A530 
4              PowerShot A2300  PowerShot A2300 
5              PowerShot A720 IS  PowerShot A720 IS 
6 PowerShot SD880 IS (Digital IXUS 870 IS, IXY Digital 920 IS, IXY 999) PowerShot SD880 IS 

數據幀我想更新(我知道我可以以某種方式,而不是未知的使用NA - 但它包括了清晰)

InputDF <- data.frame(Capture_Device = c("EOS DIGITAL REBEL XTI", "EOS 400D", "IXY Digital 920 IS", "PowerShot A530"), Standard = rep("Unknown", 4), stringsAsFactors=FALSE) 
    InputDF 

     Capture_Device Standard 
1 EOS DIGITAL REBEL XTI Unknown 
2    EOS 400D Unknown 
3 IXY Digital 920 IS Unknown 
4  PowerShot A530 Unknown 

因此,如果InputDF $ Capture_Device在LookupDF $ Testr出現在任何地方,我要與相應的LookupDF $ StandardName更新InputDF $標準

因此,所需的結果應該是這樣的:

> InputDF 

Capture_Device    Standard 
1 EOS DIGITAL REBEL XTI EOS DIGITAL REBEL XTI 
2    EOS 400D EOS DIGITAL REBEL XTI 
3 IXY Digital 920 IS PowerShot SD880 IS 
4  PowerShot A530  PowerShot A530 

我已經試過的東西沿着這些路線:

InputDF$Standard <- LookupDF[pmatch(InputDF$Capture_Device, LookupDF$Testr, duplicates.ok = TRUE),2] # Works for exact match - 1st/4th entries 
InputDF$Standard <- LookupDF[charmatch(InputDF$Capture_Device, LookupDF$Testr),2] # Works for exact match at start => 1st/4th entries 

InputDF$Standard <- LookupDF[agrep(InputDF$Capture_Device, LookupDF$Testr, max.distance=0.0),2] #error message below 

Warning message: 
    In agrep(InputDF$Capture_Device, LookupDF$Testr, max.distance = 0) : 
    argument 'pattern' has length > 1 and only the first element will be used 

所以我只能得到一個正確的結果,其中所搜索的字符串是在LookupDF $ Testr字符串的開頭(或唯一的值),但如果它不是在別處w ^在字符串中。所以,我可以得到InputDF行1和4的工作,但不是2和3.

有關我如何正確執行此操作的任何想法? 謝謝,弗蘭克

+0

感謝您的幫助理查德 - 這工作得很好。由於我只對1個「標準」值感興趣,所以我選擇使用第一個返回的匹配,因此得到: 'InputDF $ Standard < - with(LookupDF,{} {}} { )strsplit(toString(StandardName [grepl(x,Testr)]),「,」)[[1]] [1]) } 這看起來有點笨重,但效果很好。 – FrankC

回答

0

你可以使用

InputDF$Standard <- with(LookupDF, { 
    sapply(InputDF$Capture_Device, function(x) StandardName[grepl(x, Testr)]) 
}) 

這導致InputDF變化:

InputDF 
#   Capture_Device    Standard 
# 1 EOS DIGITAL REBEL XTI EOS DIGITAL REBEL XTI 
# 2    EOS 400D EOS DIGITAL REBEL XTI 
# 3 IXY Digital 920 IS PowerShot SD880 IS 
# 4  PowerShot A530  PowerShot A530 

但是,如果有兩個或兩個以上的一臺設備,將是更安全的比賽在上面的電話中用toString()包裝StandardName[grepl(x, Testr)],以確保您不會從sapply()獲得清單結果。這也允許在「標準」欄中顯示所有匹配項。

相關問題