【问题标题】:How do I make this nested for loop work faster如何使这个嵌套的 for 循环更快地工作
【发布时间】:2014-08-20 00:38:03
【问题描述】:

我的数据如下图:

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 循环相同。请指教。谢谢

【问题讨论】:

    标签: r for-loop apply lapply


    【解决方案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" 
    

    【讨论】:

      【解决方案2】:

      这应该更快:

      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)| ...
      

      然后我们将gregexprregmatches结合使用,这样我们就得到了txt$txt中每个元素的匹配列表。

      最后,使用简单的sapply,对于列表中的每个元素,我们连接匹配的城市(在删除重复项后,即多次提及的城市)。

      【讨论】:

        【解决方案3】:

        这是使用stringi 包中的stri_extract_first_regex 的可能性:

        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
        

        【讨论】:

        • 请注意,这只会找到第一个匹配项,因此如果“bangalore”和“airoli”都出现在同一个字符串中,它将不会找到。您应该改用 stri_extract_all_regex
        猜你喜欢
        • 2020-06-07
        • 2022-01-26
        • 1970-01-01
        • 2019-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多