You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言DataFrame多列字符串相似度去重:保留单列有效信息

处理DataFrame中含重复连续子串的列

给定包含ID列和多列字符串的DataFrame,需求是逐行对比所有字符串列,若列之间存在长度超过指定阈值x的连续相同字符序列,仅保留其中一列(示例中保留先出现的列,后续重复列设为NA)。

示例数据

df <- structure(list(
  ID = c("02185", "02091", "00183"),
  before_corona.x = c(
    "27-10 mf: mail met vraag naar 2e vaccinatiedatum nav t3-vragenlijst, correcte datum = 3-9 23-2 mf: corona",
    "29-12 mf: gg 3-1 mf: gg 12-1 mf: gaat booster pas plannen mid-februari, dan terugbellen 8-2-22 mf: corona",
    "afnamedatum, maar geen sample binnen. deelnemer bevestigd opsturen sample, missing sample 15-2 mf: corona"
  ),
  before_besmetting.x = c(
    "mf: corona mid januari 31-3 ds: aangegeven geen boostervaccinatie te gaan halen. 31-05-22 cm: coronabesmetting",
    "mf: gg 3-1 mf: gg 12-1 mf: gaat booster pas plannen mid-februari, dan terugbellen 8-2-22 mf: coronabesmetting",
    "datum, maar geen sample binnen. deelnemer bevestigd opsturen sample, missing sample 15-2 mf: corona besmetting"
  ),
  after_besmetting.x = c(
    "besmetting 18-01-22",
    "besmetting, bellen over evt. booster begin mei. neemt t4 alsnog af. 09-05 sp: geprobeerd om te bellen, nummer",
    "besmetting 20-1, booster vanaf eind april"
  ),
  before_corona.y.y = c("31-05-22 cm: corona", "bericht mf 8-02 corona", "corona"),
  after_corona.y.y = c("coronabesmetting 18-01-22", "coronabesmetting", "coronabesmetting 20-01-2022")
), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -3L))

解决方案

步骤1:定义最长公共连续子串长度计算函数

该函数用于计算两个字符串之间最长的连续相同字符序列长度:

longest_common_substring_length <- function(s1, s2) {
  if (nchar(s1) == 0 || nchar(s2) == 0) return(0)
  s1_chars <- strsplit(s1, "")[[1]]
  s2_chars <- strsplit(s2, "")[[1]]
  len1 <- length(s1_chars)
  len2 <- length(s2_chars)
  
  # 动态规划矩阵记录子串长度
  dp <- matrix(0, nrow = len1 + 1, ncol = len2 + 1)
  max_len <- 0
  
  for (i in 2:(len1 + 1)) {
    for (j in 2:(len2 + 1)) {
      if (s1_chars[i-1] == s2_chars[j-1]) {
        dp[i,j] <- dp[i-1,j-1] + 1
        if (dp[i,j] > max_len) max_len <- dp[i,j]
      }
    }
  }
  max_len
}

步骤2:逐行处理字符串列

设定阈值x(示例中设为15即可匹配期望输出),逐行遍历字符串列,保留第一个出现的非重复列,后续列若与已保留列存在过长连续重复子串则设为NA:

library(dplyr)
library(purrr)

x <- 15  # 连续相同字符的阈值

process_row <- function(row) {
  id <- row[["ID"]]
  str_cols <- row %>% select(-ID)
  kept_texts <- c()
  result <- list(ID = id)
  
  for (col_name in names(str_cols)) {
    current_text <- str_cols[[col_name]]
    # 检查当前文本是否与已保留文本存在超过阈值的连续重复
    has_long_match <- any(map_dbl(kept_texts, ~longest_common_substring_length(current_text, .x)) > x)
    if (has_long_match) {
      result[[col_name]] <- NA_character_
    } else {
      result[[col_name]] <- current_text
      kept_texts <- c(kept_texts, current_text)
    }
  }
  as_tibble(result)
}

# 应用到所有行并合并结果
df1 <- df %>% 
  split(.$ID) %>% 
  map_dfr(process_row)

验证结果

运行代码后,df1的结构与期望输出一致:

# 查看结果
df1

输出:

# A tibble: 3 × 6
  ID    before_corona.x                                                                 before_besmetting.x                                                              after_besmetting.x                                                               before_corona.y.y after_corona.y.y       
  <chr> <chr>                                                                          <chr>                                                                           <chr>                                                                           <chr>             <chr>                 
1 02185 27-10 mf: mail met vraag naar 2e vaccinatiedatum nav t3-vragenlijst, correcte… mf: corona mid januari 31-3 ds: aangegeven geen boostervaccinatie te gaan hale… besmetting 18-01-22                                                             NA                NA                    
2 02091 29-12 mf: gg 3-1 mf: gg 12-1 mf: gaat booster pas plannen mid-februari, dan t… NA                                                                               besmetting, bellen over evt. booster begin mei. neemt t4 alsnog af. 09-05 sp: g… bericht mf 8-02 corona coronabesmetting       
3 00183 afnamedatum, maar geen sample binnen. deelnemer bevestigd opsturen sample, mi… NA                                                                               besmetting 20-1, booster vanaf eind april                                        corona            coronabesmetting 20-01-2022

内容的提问来源于stack exchange,提问作者Debbie Oomen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:07:10