我正在尝试在R中的数据帧之间进行简单的查找/更新,但没有成功。它基于一些Flickr数据,其中一些相机有许多不同的名称 - 我想将其中的每一个转换为标准名称。我在这里看了类似的答案 - 但它们似乎没有处理我匹配子字符串的情况,这可能出现在列中的任何位置。
我在这里放了一组简化的数据来说明我的问题:
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)"))
一点点整理+创建一个新列(我决定使用第一个摄像机名称作为“标准名称”):
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 $ Standard
因此,所需的结果应如下所示:
> 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字符串的开头(或唯一的值),但如果它在字符串中的其他位置则不会。所以,我可以让InputDF第1行和第4行工作,但不能使用2和3。
有关如何正确执行此操作的任何想法? 谢谢,弗兰克
答案 0 :(得分: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
但是,如果某个设备有两个或多个匹配项,那么使用StandardName[grepl(x, Testr)]
将toString()
包裹在上述呼叫中会更安全,以确保您不会获得来自sapply()
的列表结果。这也允许所有比赛显示在&#34;标准&#34;柱。