代码之家  ›  专栏  ›  技术社区  ›  carozimm

根据R中另一列中的值替换一列中第二次出现的字符串

  •  0
  • carozimm  · 技术社区  · 8 年前

    以下是一个示例数据帧:

    a <- c("cat", "dog", "mouse")
    b <- c("my cat is a tabby cat and is a friendly cat", "walk the dog", "the mouse is scared of the other mouse")
    df <- data.frame(a,b)
    

    我希望能够删除b列a列中第二次出现的值。

    这是我想要的输出:

    a      b
    cat    my cat is a tabby and is a friendly cat
    dog    walk the dog
    mouse  the mouse is scared of the other
    

    我尝试了gsub和一些stringr函数的不同组合,但我甚至无法删除第二个(仅第二个)出现在b列a列中的字符串 this 一个,但我不熟悉Perl,无法将其转换为R。

    谢谢

    4 回复  |  直到 8 年前
        1
  •  1
  •   G5W    8 年前

    构建正确的正则表达式需要一些工作。

    P1 = paste(a, collapse="|")
    PAT = paste0("((", P1, ").*?)(\\2)")
    
    sub(PAT, "\\1", b, perl=TRUE)
    [1] "my cat is a tabby  and is a friendly cat"
    [2] "walk the dog"                            
    [3] "the mouse is scared of the other "   
    
        2
  •  1
  •   carozimm    8 年前

    实际上,我已经找到了另一个解决方案,虽然时间更长,但对于其他regex初学者来说可能更清楚:

    library(stringr)
    # Replace first instance of col a in col b with "INTERIM" 
    df$b <- str_replace(b, a, "INTERIM")
    
    # Now that the original first instance of col a is re-labeled to "INTERIM", I can again replace the first instance of col a in col b, this time with an empty string
    df$b <- str_replace(df$b, a, "")
    
    # And I can re-replace the re-labeled "INTERIM" to the original string in col a
    df$b <- str_replace(df$b, "INTERIM", a)
    
    # Trim "double" whitespace
    df$b <- str_replace(gsub("\\s+", " ", str_trim(df$b)), "B", "b")
    
    
    df
    a            b
    cat          my cat is a tabby and is a friendly cat
    dog          walk the dog
    mouse        the mouse is scared of the other
    
        3
  •  0
  •   Andrew Gustar    8 年前

    你可以这样做。。。

    library(stringr)
    df$b <- str_replace(df$b, 
                        paste0("(.*?",df$a,".*?) ",df$a), 
                        "\\1")
    
    df
          a                                       b
    1   cat my cat is a tabby and is a friendly cat
    2   dog                            walk the dog
    3 mouse        the mouse is scared of the other
    

    正则表达式查找第一个字符串 df$a 在它的某个地方,然后是一个空间和另一个空间 df$年 。捕获组是第二次出现之前的空格内的文本(由 (...) ),并且整个文本(包括第二个匹配项)被捕获组替换 \\1 (具有删除第二个 df$年 以及它前面的空格)。第二次之后的任何事情 df$年 不受影响。

        4
  •  0
  •   hello_friend    6 年前

    基本R,拆分应用组合解决方案:

    # Split-apply-combine: 
    
    data.frame(do.call("rbind", lapply(split(df, df$a), function(x){
    
            b <- paste(unique(unlist(strsplit(x$b, "\\s+"))), collapse = " ")
    
            return(data.frame(a = x$a, b = b))
    
          }
    
        )
    
      ), 
    
      stringsAsFactors = FALSE, row.names = NULL
    
    )
    

    数据:

    df <- data.frame(a = c("cat", "dog", "mouse"),
                     b = c("my cat is a tabby cat and is a friendly cat", "walk the dog", "the mouse is scared of the other mouse"), 
                     stringsAsFactors = FALSE)