【问题标题】:Identify duplicate Word in a string between rows识别行之间字符串中的重复单词
【发布时间】:2019-04-26 12:17:42
【问题描述】:

我有一列有 5000 行。我的目标是检查每一行是否有重复的单词。例如:

第一行:我叫鲍比

第二排:我叫鲍比

第三排:这是你的房子

从上面的例子我们可以看出,第一行和第二行之间有3个重复词,第二行和第三行之间只有1个重复词。我想让每行有 3 个或更多重复单词成为同一个单词。例如:

我叫鲍比

我叫鲍比

这是你的家

我是 r 的新手。你能帮帮我吗?

【问题讨论】:

  • 您是否总是希望使用数据框中的第一行来替换后面的行?如果您也有一行My cat is Boby 怎么办?在这种情况下应该怎么办?
  • 看你给出的例子,在我看来你想做模糊替换。如果我是对的,您可能需要检查 stringdist 包。
  • 尽管已经发布了答案,但这是一个非常不清楚的问题。

标签: r string duplicates


【解决方案1】:

使用tidyverse 的解决方案。我创建了一个名为dat 的示例数据框,有五行。请注意,该列是字符,而不是因子。请注意这个例子的结果。如您所见,第 3 行和第 4 行有很大的不同,但是因为它们有三个常用词,并且因为第 3 行与第 2 行和第 1 行相似,所以最终将第 4 行替换为第 1 行。也许还可以。我只是想告诉你,你描述的情况可能会导致这种情况。

library(tidyverse)

dat2 <- dat %>%
  # Split the sentence
  mutate(V2 = str_split(V1, pattern = " ")) %>%     
  # Create a new column for the next word
  mutate(V3 = lead(V2)) %>%    
  # Count the number of intersection
  mutate(V4 = lag(map2_int(V2, V3, ~length(intersect(.x, .y))),
                  default = 0L)) %>%    
  # If >= 3 words are the same, set to be NA, otherwise the same as V1
  mutate(V5 = if_else(V4 >= 3, NA_character_, V1)) %>%   
  # Fill the NA based on the previous row
  fill(V5) %>%
  # Select column V1 and V5
  select(V1, V5)

dat2

#                            V1               V5
# 1            My name is Bobby My name is Bobby
# 2             My name is Boby My name is Bobby
# 3              My name is Boy My name is Bobby
# 4 This is your house name Boy My name is Bobby
# 5                R is awesome     R is awesome

数据

dat <- read.table(text = "'My name is Bobby'
                          'My name is Boby'
                          'My name is Boy'
                          'This is your house name Boy'
                          'R is awesome'",
                  stringsAsFactors = FALSE)

【讨论】:

    【解决方案2】:

    不需要 57 编译包依赖“verse”:

    library(stringi) # helpful string function that stringr builds a crutch around
    
    data.frame(
      V1 = c("My name is Bobby", "My name is Boby", "This is your house"),
      stringsAsFactors = FALSE
    ) -> dat
    
    for (idx in 1:(length(dat$V1)-1)) {
    
      stri_split_boundaries( # split the strings
        stri_trans_tolower(dat$V1[idx:(idx+1)]), # turn elements lower case for easier comparison
        type = "word",  # split into words
        skip_word_none = TRUE # ignore whitespace
      ) -> words
    
      if (sum(words[[1]] %in% words[[2]]) >= 3) { # compare the word sets
        dat[idx+1, "V1"] <- dat[idx, "V1"]
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-24
      • 1970-01-01
      • 1970-01-01
      • 2016-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      相关资源
      最近更新 更多