2014-12-25 3 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 + создать новый столбец (я решил использовать название 1-й камеры, как «стандартное имя») :

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 каким-то образом вместо Unknown - но он включен для ясности)

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, я хочу, чтобы обновить InputDF $ Стандартная с соответствующим LookupDF $ StandardName

Поэтому требуемый результат должен выглядеть следующим образом:

> 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 

I «ве пробовали вещи вдоль этих линий:

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 (или единственное значение), но если это в другом месте вес в строке. Итак, я могу получить строки InputFF 1 и 4 для работы, но не 2 и 3.

Любые идеи о том, как я могу сделать это правильно? Спасибо, Франк

+0

Спасибо за вашу помощь Ричард - это работает очень хорошо. Поскольку меня интересует только одно «стандартное» значение, я выбираю использовать первое возвращенное совпадение и получаю: 'InputDF $ Standard <- with (LookupDF, { sapply (InputDF $ Capture_Device, function (x) strsplit (toString (стандартное имя [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 

Однако, в случае, если есть два или более матчей на одном устройстве было бы безопаснее оберните StandardName[grepl(x, Testr)] в вышеуказанный вызов с toString(), чтобы убедиться, что вы не получили результат из sapply(). Это также позволяет отображать все совпадения в столбце «Стандарт».