R语言用grepl匹配名单从字符串提取会面人名并添加新列的问题
R实现会面对象提取方案
核心处理逻辑
- 提取活动描述中所有匹配的姓名列表
- 过滤掉当前行主体本人的姓名
- 多个匹配结果拼接为空格分隔的字符串,无匹配则返回NA
主流tidyverse实现(易读性高,适配后续网络分析需求)
# 加载所需包 library(dplyr) library(stringr) # 构造测试数据 name <- c("Dupont","Dupuy","Smith") activity <- c("On that day, he had lunch with Dupuy in London.", "She had lunch with Dupont and then went to Brighton to meet Smith.", "Smith remembers that he was tired on that day.") df <- data.frame(name, activity) # 预定义所有人员姓名的正则匹配模式,用|分隔表示或匹配 name_list <- unique(df$name) name_pattern <- paste0(name_list, collapse = "|") # 处理met_with字段 df <- df %>% rowwise() %>% mutate( # 提取当前activity中所有出现的姓名 matched_names = list(str_extract_all(activity, name_pattern)[[1]]), # 剔除本人姓名,去重后拼接 met_with = setdiff(matched_names, name) %>% unique() %>% paste(collapse = " "), # 无匹配结果时转为NA met_with = ifelse(met_with == "", NA, met_with) ) %>% select(-matched_names) %>% ungroup()
适配网络分析的边列表直接生成方案
不需要先拼接为字符串再拆分,可直接生成符合网络分析要求的边表:
edge_df <- df %>% rowwise() %>% mutate(met = list(setdiff(str_extract_all(activity, name_pattern)[[1]], name))) %>% unnest_longer(met) %>% filter(!is.na(met)) %>% select(from = name, to = met, activity)
基础R实现(无需加载第三方包)
name_list <- unique(df$name) df$met_with <- NA for (i in seq(nrow(df))) { # 提取所有匹配的姓名 all_matched <- name_list[sapply(name_list, function(x) grepl(x, df$activity[i]))] # 剔除本人 filtered_matched <- setdiff(all_matched, df$name[i]) # 处理结果 df$met_with[i] <- ifelse(length(filtered_matched) == 0, NA, paste(filtered_matched, collapse = " ")) }
优化提示:如果要避免部分匹配(比如避免
Dup匹配到Dupont),可以将匹配规则调整为带单词边界的模式:name_pattern <- paste0("\\b", name_list, "\\b", collapse = "|")
内容的提问来源于stack exchange,提问作者LLS
相关产品推荐
相关产品推荐

