2014-06-29 1 views
2

Моих данных, как показано ниже:Как мне сделать это вложенным для работы петли быстрее

txt$txt: 

my friend stays in adarsh nagar 
I changed one apple one samsung S3 n one sony experia z. 
Hi girls..Friends meet at bangalore 
what do u think of ccd at bkc 

У меня есть исчерпывающий список названий городов. Листинг некоторые из них ниже:

city: 

ahmedabad 
adarsh nagar 
airoli 
bangalore 
bangaladesh 
banerghatta Road 
bkc 
calcutta 

Я ищу название городов (из списка «города» у меня есть) в txt$txt и извлекая их в другой столбец, если они присутствуют. Таким образом, простой цикл ниже работает для меня ... но это занимает много времени на большом наборе данных.

for(i in 1:nrow(txt)){ 
    a <- c() 
    for(j in 1:nrow(city)){ 
     a[j] <- grepl(paste("\\b",city[j,1],"\\b", sep = ""),txt$txt[i])   
    } 
    txt$city[i] <- ifelse(sum(a) > 0, paste(city[which(a),1], collapse = "_"), "NONE") 
} 

Я попытался использовать функцию apply, и это максимум, на который я мог бы добраться.

apply(as.matrix(txt$txt), 1, function(x){ifelse(sum(unlist(strsplit(x, " ")) %in% city[,1]) > 0, paste(unlist(strsplit(x, " "))[which(unlist(strsplit(x, " ")) %in% city[,1])], collapse = "_"), "NONE")}) 
[1] "NONE"  "NONE"  "bangalore" "bkc" 

Desired Output: 
> txt 
                 txt   city 
1       my friend stays in adarsh nagar adarsh nagar 
2 I changed one apple one samsung S3 n one sony experia z.   NONE 
3      Hi girls..Friends meet at bangalore bangalore 
4       what do u think of ccd at bkc   bkc  

Мне нужен более быстрый процесс в R, который делает то же самое, что и цикл for выше. Пожалуйста, порекомендуйте. Благодаря

ответ

1

Это должно быть намного быстрее:

bigPattern <- paste('(\\b',city[,1],'\\b)',collapse='|',sep='') 
txt$city <- sapply(regmatches(txt$txt,gregexpr(bigPattern,txt$txt)),FUN=function(x) ifelse(length(x) == 0,'NONE',paste(unique(x),collapse='_'))) 

Объяснение:

в первой строке мы строим большой регулярное выражение, соответствующее всем городам, например :

(\\bahmedabad\\b)|(\\badarsh nagar\\b)|(\\bairoli\\b)| ... 

Затем мы используем gregexpr в сочетании с regmatches, таким образом, мы получаем список совпадений для каждого элемента в txt$txt.

Наконец, с простым sapply, для каждого элемента списка мы объединяем сопоставленные города (после удаления дубликатов, то есть городов, упомянутых более одного раза).

3

Вот возможность использования stri_extract_first_regex из stringi пакета:

library(stringi) 

# prepare some data 
df <- data.frame(txt = c("in adarsh nagar", "sony experia z", "at bangalore")) 
city <- c("ahmedabad", "adarsh nagar", "airoli", "bangalore") 

df$city <- stri_extract_first_regex(str = df$txt, regex = paste(city, collapse = "|")) 

df 
#    txt   city 
# 1 in adarsh nagar adarsh nagar 
# 2 sony experia z   <NA> 
# 3 at bangalore bangalore 
+0

Обратите внимание, что это найти только первый матч, поэтому он не будет найти, например, «Бангалора» и «airoli», если оба присутствуют в одной и той же строке. Вместо этого следует использовать stri_extract_all_regex – digEmAll

1

Попробуйте это:

# YOUR DATA 
########## 
txt <- readLines(n = 4) 
my friend stays in adarsh nagar and airoli 
I changed one apple one samsung S3 n one sony experia z. 
Hi girls..Friends meet at bangalore 
what do u think of ccd at bkc 

city <- readLines(n = 8) 
ahmedabad 
adarsh nagar 
airoli 
bangalore 
bangaladesh 
banerghatta Road 
bkc 
calcutta 

# MATCHING 
########## 
matches <- unlist(setNames(lapply(city, grep, x = txt, fixed = TRUE), 
          city)) 
(res <- (sapply(1:length(txt), function(x) 
    paste0(names(matches)[matches == x], collapse = "___")))) 
# [1] "adarsh nagar___airoli" ""      
# [3] "bangalore"    "bkc" 
Смежные вопросы