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

如何结合str_detect与lag/lead函数跨多行查找目标匹配项?

问题需求

现有处理单行lag()/lead()匹配的函数,但需要优化:当目标行的紧邻前后行无匹配项时,查找当前行前后最近的、满足str_detect=TRUE的实例(例如匹配项出现在前三行),完成对应字符串替换。

当前使用的包

library(tidytext)
library(dplyr)
library(stringr)

原单行匹配函数

匹配前一行的函数

# 仅匹配前一行的函数
r_sen_from_states_alabama_lag <- function(x){
  ifelse(str_detect(x, regex("the senator from Alabama",ignore_case = TRUE))==TRUE & str_detect(lag(x),"^Mr\\. SHELBY \\(R; Alabama\\):")==TRUE,
         str_replace(x,regex("the senator from Alabama", ignore_case = TRUE),"senator Shelby"),
         ifelse(str_detect(x, regex("the senator from Alabama", ignore_case = TRUE))==TRUE & str_detect(lag(x),"^Mr\\. SESSIONS \\(R; Alabama\\):")==TRUE,
                str_replace(x, regex("the senator from Alabama",ignore_case = TRUE), "senator Sessions"),x))
}

匹配后一行的函数

# 仅匹配后一行的函数
r_sen_from_states_alabama_lead <- function(x){
  ifelse(str_detect(x, regex("the senator from Alabama",ignore_case = TRUE))==TRUE & str_detect(lead(x),"^Mr\\. SHELBY \\(R; Alabama\\):")==TRUE,
         str_replace(x,regex("the senator from Alabama", ignore_case = TRUE),"senator Shelby"),
         ifelse(str_detect(x, regex("the senator from Alabama", ignore_case = TRUE))==TRUE & str_detect(lead(x),"^Mr\\. SESSIONS \\(R; Alabama\\):")==TRUE,
                str_replace(x, regex("the senator from Alabama",ignore_case = TRUE), "senator Sessions"),x))
}

test_df_try_1 <- as.data.frame(r_sen_from_states_alabama_lead(test_df))

测试数据

# 测试数据
test_col <- c("Mr. SHELBY (R; Alabama): I acknowledge this is a test.",
              "Mrs. MURRAY (D; Washington): I say to my friend, the senator from Alabama, that they are wrong.",
              "Mr. SHELBY (R; Alabama): I do not agree with my colleague.",
              "Mr. FRIST (R; Tennessee): The senator from Alabama is correct, senator Murray.",
              "Mr. SHELBY (R; Alabama): I thank the majority leader for their support.",
              "Mr. SESSIONS (R; Alabama): I am proud of my junior, the senator from Alabama.",
              "Mr. SHELBY (R; Alabama): To my senior peer, the senator from Alabama, I say great things.",
              "Ms. PEABODY (I; Atlantis): This is just to fill space.",
              "Mr. Quail (Q; Nowhere): Match this one, the senator from Alabama, with the senator at the bottom.",
              "Ms. PEABODY (I; Atlantis): This is just to fill space.",
              "Ms. PEABODY (I; Atlantis): This is just to fill space!",
              "Ms. PEABODY (I; Atlantis): This is just to fill space?",
              "Mr. SESSIONS (R; Alabama): Match this one with Quail.")

test_df <- data.frame(test_col)
colnames(test_df) <- c("speeches")

期望输出

向前查找(最近的前序匹配)结果

1   Mr. SHELBY (R; Alabama): I acknowledge this is a test.
2   Mrs. MURRAY (D; Washington): I say to my friend, senator Shelby, that they are wrong.
3   Mr. SHELBY (R; Alabama): I do not agree with my colleague.
4   Mr. FRIST (R; Tennessee): senator Shelby is correct, senator Murray.
5   Mr. SHELBY (R; Alabama): I thank the majority leader for their support.
6   Mr. SESSIONS (R; Alabama): I am proud of my junior, senator Shelby.
7   Mr. SHELBY (R; Alabama): To my senior peer, senator Sessions, I say great things.
8   Ms. PEABODY (I; Atlantis): This is just to fill space.
9   Mr. Quail (Q; Nowhere): Match this one, senator Shelby, with the senator before.
10  Ms. PEABODY (I; Atlantis): This is just to fill space.
11  Ms. PEABODY (I; Atlantis): This is just to fill space!
12  Ms. PEABODY (I; Atlantis): This is just to fill space?
13  Mr. SESSIONS (R; Alabama): Match this one with Quail.

注:第9行匹配的是前数第2行的Shelby

向后查找(最近的后序匹配)结果

1  Mr. SHELBY (R; Alabama): I acknowledge this is a test.
2  Mrs. MURRAY (D; Washington): I say to my friend, senator Shelby, that they are wrong.
3  Mr. SHELBY (R; Alabama): I do not agree with my colleague.
4  Mr. FRIST (R; Tennessee): senator Shelby is correct, senator Murray.
5  Mr. SHELBY (R; Alabama): I thank the majority leader for their support.
6  Mr. SESSIONS (R; Alabama): I am proud of my junior, senator Shelby.
7  Mr. SHELBY (R; Alabama): To my senior peer, senator Sessions, I say great things.
8  Ms. PEABODY (I; Atlantis): This is just to fill space.
9  Mr. Quail (Q; Nowhere): Match this one, senator Sessions, with the senator at the bottom.
10 Ms. PEABODY (I; Atlantis): This is just to fill space.
11 Ms. PEABODY (I; Atlantis): This is just to fill space!
12 Ms. PEABODY (I; Atlantis): This is just to fill space?
13 Mr. SESSIONS (R; Alabama): Match this one with Quail.

注:第6行匹配的是后数第7行的Shelby,第9行匹配的是后数第4行的Sessions


解决方案

核心思路:先标记所有Shelby/Sessions的行,再向前/向后填充这些标记,让每行对应最近的匹配项,最后根据标记替换目标字符串。

1. 向前查找(最近前序匹配)实现

test_df_lag <- test_df %>%
  # 标记当前行对应的参议员
  mutate(senator = case_when(
    str_detect(speeches, "^Mr\\. SHELBY \\(R; Alabama\\):") ~ "Shelby",
    str_detect(speeches, "^Mr\\. SESSIONS \\(R; Alabama\\):") ~ "Sessions",
    TRUE ~ NA_character_
  )) %>%
  # 向前填充NA,得到每行最近的前序参议员
  fill(senator, .direction = "down") %>%
  # 替换目标字符串
  mutate(speeches = ifelse(
    str_detect(speeches, regex("the senator from Alabama", ignore_case = TRUE)),
    str_replace(speeches, regex("the senator from Alabama", ignore_case = TRUE), 
                str_c("senator ", senator)),
    speeches
  )) %>%
  select(-senator)

2. 向后查找(最近后序匹配)实现

test_df_lead <- test_df %>%
  mutate(senator = case_when(
    str_detect(speeches, "^Mr\\. SHELBY \\(R; Alabama\\):") ~ "Shelby",
    str_detect(speeches, "^Mr\\. SESSIONS \\(R; Alabama\\):") ~ "Sessions",
    TRUE ~ NA_character_
  )) %>%
  # 向后填充NA,得到每行最近的后序参议员
  fill(senator, .direction = "up") %>%
  mutate(speeches = ifelse(
    str_detect(speeches, regex("the senator from Alabama", ignore_case = TRUE)),
    str_replace(speeches, regex("the senator from Alabama", ignore_case = TRUE), 
                str_c("senator ", senator)),
    speeches
  )) %>%
  select(-senator)

验证结果

运行上述代码后,test_df_lag会输出向前查找的期望结果,test_df_lead会输出向后查找的期望结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 13:32:02