2014-12-25 24 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()获得清单结果。这也允许在“标准”栏中显示所有匹配项。

相关问题