2017-02-03 1 views
1

Я хочу, чтобы grep значения из нескольких столбцов, а затем назначить приоритет в случае возникновения конфликта. Я был в состоянии написать работоспособный код, но это слишком повторяющиеся в том, что я на самом деле не в полном мере используя силу векторизованных операций в R. Я искал решение с lapply, sapply и т.д.Рекурсивно применять grep на основе значений из нескольких столбцов

Я попытался баловаться вокруг с lapply, но застрял.

Вот мои данные:

dput(DF) 
structure(list(S6 = c("FED AIR FORCE", "FED AIR FORCE", "FED AIR FORCE", 
"FED MARINES", "FED MARINES", "FED MARINES", "FED NAVY", "FED NAVY", 
"FED NAVY", "FED NAVY", "FEDERAL", "STATE", "STATE"), S.Name = c("MARINE", 
"ARMY", "AIR FORCE", "MARINE", "ARMY", "AIR FORCE", "MARINE", 
"ARMY", "AIR FORCE", "NAVY", "NAVY", "AIR FORCE", "FEDERAL"), 
    Dept = c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_), Number = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 
    10, 11, 12, 12)), .Names = c("S6", "S.Name", "Dept", "Number" 
), row.names = c(NA, 13L), class = "data.frame") 

Вот мой код, который работает:

Divisions<-c("Air Force", "Army", "Navy", "Marine") 
DF[grep("AIR FORCE",DF$S.Name,ignore.case = TRUE),"Dept"]<-"Air Force" 
DF[grep("Army",DF$S.Name,ignore.case = TRUE),"Dept"]<-"Army" 
DF[grep("Navy",DF$S.Name,ignore.case = TRUE),"Dept"]<-"Navy" 
DF[grep("Marine",DF$S.Name,ignore.case = TRUE),"Dept"]<-"Marine" 

DF[grep("AIR FORCE",DF$S6,ignore.case = TRUE),"Dept"]<-"Air Force" 
DF[grep("Army",DF$S6,ignore.case = TRUE),"Dept"]<-"Army" 
DF[grep("Navy",DF$S6,ignore.case = TRUE),"Dept"]<-"Navy" 
DF[grep("Marine",DF$S6,ignore.case = TRUE),"Dept"]<-"Marine" 

Комментарий: Сначала я прочитал S.Name, если есть совпадение, я пишу матч , Затем я прочитал S6, если есть совпадение, я перезаписываю его. Таким образом, S6 имеет приоритет над S.Name.

Ожидаемые результаты после выполнения выше операций:

dput(DF) 
structure(list(S6 = c("FED AIR FORCE", "FED AIR FORCE", "FED AIR FORCE", 
"FED MARINES", "FED MARINES", "FED MARINES", "FED NAVY", "FED NAVY", 
"FED NAVY", "FED NAVY", "FEDERAL", "STATE", "STATE"), S.Name = c("MARINE", 
"ARMY", "AIR FORCE", "MARINE", "ARMY", "AIR FORCE", "MARINE", 
"ARMY", "AIR FORCE", "NAVY", "NAVY", "AIR FORCE", "FEDERAL"), 
    Dept = c("Air Force", "Air Force", "Air Force", "Marine", 
    "Marine", "Marine", "Navy", "Navy", "Navy", "Navy", "Navy", 
    "Air Force", NA), Number = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
    11, 12, 12)), .Names = c("S6", "S.Name", "Dept", "Number" 
), row.names = c(NA, 13L), class = "data.frame") 

Я хочу, чтобы иметь возможность векторизации это ... то есть. использовать lapply


Вот что я пытался с lapply:

l<-lapply(Divisions,function (x) {sort(unique(append(grep(x,DF$S.Name,ignore.case = TRUE),grep(x,DF$S6,ignore.case = TRUE))))}) 

К сожалению, я не знаю, как назначить приоритет, и кормить значения обратно к кадру данных. Буду признателен за любые мысли.

ответ

1

Мы можем использовать str_extract, чтобы извлечь определенные слова в столбце «s6» от «Дивизиона» vector по paste ТРАЕКТОРИЯМ элементов вместе, а затем использовать gsub, чтобы изменить его на ГорбатыйРегистр путем сопоставления заглавной буквы после границы слова (\\b), за которым следуют одна или несколько заглавных букв (([A-Z]+)), захваченных как в качестве группы, так и взамен, мы используем обратную ссылку первого (\\1), а затем определяем строчный регистр (\\L) для второй обратной ссылки (\\2)

library(stringr) 
DF$Dept <- gsub("(\\b[A-Z])([A-Z]+)", "\\1\\L\\2", str_extract(DF$S6, 
     paste(toupper(Divisions), collapse="|")), perl = TRUE) 
DF$Dept 
#[1] "Air Force" "Air Force" "Air Force" "Marine" "Marine" "Marine" "Navy"  "Navy"  "Navy"  "Navy"  NA   
#[12] NA   NA  

I f есть NA элементов в разделе «Dept», затем измените его, применяя тот же метод в «S.Name»

i1 <- is.na(DF$Dept) 
DF$Dept[i1] <- gsub("(\\b[A-Z])([A-Z]+)", "\\1\\L\\2", 
    str_extract(DF$S.Name[i1], paste(toupper(Divisions), collapse="|")), perl = TRUE) 
DF$Dept 
#[1] "Air Force" "Air Force" "Air Force" "Marine" "Marine" "Marine" "Navy"  "Navy"  "Navy"  "Navy"  "Navy"  
#[12] "Air Force" NA  
+0

Спасибо. Не могли бы вы объяснить шаги? Кроме того, я считаю, что я действительно борюсь с регулярными выражениями. Для меня потребовалось бы один день, чтобы я придумал то, что у вас есть. У вас есть какие-либо советы о том, как я могу улучшить свои навыки с помощью регулярных выражений? – watchtower

+0

@watchtower Я обновил сообщение. Надеюсь, поможет. Вы также можете проверить http://www.regular-expressions.info/tutorial.html – akrun

+0

Еще раз спасибо за вашу помощь. Как вы думаете, мы могли бы сделать то же самое, используя 'lapply' i.e без использования регулярного выражения? – watchtower

Смежные вопросы