使用来自另一个data.frame的查找值更新data.frame中的列 - 使用子字符串匹配

时间:2014-12-25 01:47:09

标签: r match lookup flickr

我正在尝试在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。

有关如何正确执行此操作的任何想法? 谢谢,弗兰克

1 个答案:

答案 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;柱。