【问题标题】:Match and replace words in char-vector匹配和替换字符向量中的单词
【发布时间】:2020-10-29 19:17:37
【问题描述】:

我有一个带有文本行的向量,如下所示:

text<-c("Seat 1: 7e7389e3 ($2 in chips)","Seat 3: 6786517b ($1.67 in chips)","Seat 4: 878b0b52 ($2.16 in chips)","Seat 5: a822375 ($2.37 in chips)","Seat 6: 7a6252e6 ($2.51 in chips)")

我必须用其他词替换一些词,我在这样的数据框中:

df<-data.frame(codigo=c("7e7389e3","6786517b","878b0b52","a822375","7a6252e6"),
name=c("lucas","alan","ivan","lucio","donald"))

所以我想 1) 抓取“文本”的第一行 2) 检查 df 中是否有要替换的单词 3) 替换它 4) 对下一个“文本”行执行相同操作,依此类推。为了有这样的东西:

[1] "Seat 1: lucas ($2 in chips)"
[2] "Seat 3: alan ($1.67 in chips)"
[3] "Seat 4: ivan ($2.16 in chips)"
[4] "Seat 5: lucio ($2.37 in chips)"
[5] "Seat 6: donald ($2.51 in chips)"

有什么公式可以做到这一点?

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用str_replace_all 轻松做到这一点,它可以采用命名向量

    library(stringr)
    library(tibble)
    str_replace_all(text, deframe(df))
    #[1] "Seat 1: lucas ($2 in chips)"  
    #[2] "Seat 3: alan ($1.67 in chips)" 
    #[3]  "Seat 4: ivan ($2.16 in chips)"  
    #[4] "Seat 5: lucio ($2.37 in chips)" 
    #[5] "Seat 6: donald ($2.51 in chips)"
    

    【讨论】:

      【解决方案2】:

      使用sapply + gsub + Vectorize 的基本 R 选项

      unname(sapply(text,function(x) (u <- Vectorize(gsub)(df$codigo,df$name,x,fixed = TRUE))[u!=x]))
      

      给了

      [1] "Seat 1: lucas ($2 in chips)"     "Seat 3: alan ($1.67 in chips)"
      [3] "Seat 4: ivan ($2.16 in chips)"   "Seat 5: lucio ($2.37 in chips)"
      [5] "Seat 6: donald ($2.51 in chips)"
      

      【讨论】:

        【解决方案3】:

        像这样的情况是使用for 循环的绝佳机会。这很无聊,但它很有效,并且根据上一个问题在效率方面具有相当的竞争力 - regex for preserving case pattern, capitalization

        out <- text
        for (i in seq_len(nrow(df)) ) {
            out <- gsub(df$codigo[i], df$name[i], out)
        }
        out
        #[1] "Seat 1: lucas ($2 in chips)"     "Seat 3: alan ($1.67 in chips)"  
        #[3] "Seat 4: ivan ($2.16 in chips)"   "Seat 5: lucio ($2.37 in chips)" 
        #[5] "Seat 6: donald ($2.51 in chips)"
        

        【讨论】:

          【解决方案4】:

          使用tidyverse 函数尝试这种方法。看起来,如果有: ( 的模式,您可以分配一个公共拆分元素和分隔列,与df 连接,最后连接字符串以获得预期结果。代码如下:

          library(tidyverse)
          res <- text %>% as.data.frame %>% setNames(.,'v1') %>%
            mutate(v1=gsub(': ','*',v1),
                   v1=gsub(' (','*',v1,fixed=T)) %>%
            separate(v1,c('Var1','codigo','Var3'),sep='\\*') %>%
            left_join(df) %>%
            mutate(Out=paste0(Var1,': ',name,' (',Var3)) %>%
            select(Out)
          

          输出:

                                        Out
          1     Seat 1: lucas ($2 in chips)
          2   Seat 3: alan ($1.67 in chips)
          3   Seat 4: ivan ($2.16 in chips)
          4  Seat 5: lucio ($2.37 in chips)
          5 Seat 6: donald ($2.51 in chips)
          

          【讨论】:

            猜你喜欢
            • 2020-12-03
            • 1970-01-01
            • 2011-03-26
            • 2018-05-23
            • 1970-01-01
            • 2013-07-08
            • 1970-01-01
            相关资源
            最近更新 更多