R语言利用有限匹配字符按配对站点筛选数据行方法
R语言筛选配对站点before/after对应行
需求描述
提取数据中满足配对规则的行:同一行的两个位置列中,一列带事件前标识before、另一列带事件后标识after,且两列对应的站点、位置编号完全匹配。
给定测试数据如下,预期返回原数据的第2行、第5行:
dat <- data.frame(var1 = c('Green Island_one_before', 'Green Island_two_before', 'Green Island_one_after', 'Pink Island_one_before', 'Pink Island_two_after', 'Pink Island_five_after'), var2 = c('Green Island_three_before', 'Green Island_two_after', 'Green Island_one_after', 'Pink Island_four_before', 'Pink Island_two_before', 'Pink Island_six_after'), value = c(1, 7, 4, 2, 8, 3))
实现思路
核心判断逻辑分两步,逐行校验:
- 两列字符串末尾的时间标识必须刚好是一个
before、一个after,不存在两个同是before/同是after的情况 - 去掉末尾时间标识后,两列剩下的「站点名+位置编号」部分必须完全一致,代表是同一个点位的前后配对
代码方案
基础R实现(无需安装额外包)
# 定义拆分函数:分离位置前缀、时间标识 split_str <- function(col) { prefix <- sub("_(before|after)$", "", col) tag <- sub(".*_", "", col) list(prefix = prefix, tag = tag) } v1 <- split_str(dat$var1) v2 <- split_str(dat$var2) # 按条件筛选 result <- dat[ ((v1$tag == "before" & v2$tag == "after") | (v1$tag == "after" & v2$tag == "before")) & v1$prefix == v2$prefix, ]
运行后输出结果和预期完全一致:
> result var1 var2 value 2 Green Island_two_before Green Island_two_after 7 5 Pink Island_two_after Pink Island_two_before 8
tidyverse实现
如果日常用tidyverse流处理数据,也可以用以下写法:
library(dplyr) library(tidyr) result <- dat %>% mutate(rowid = row_number()) %>% pivot_longer(c(var1, var2), values_to = "str") %>% separate(str, into = c("loc", "tag"), sep = "_(?=(before|after)$)") %>% group_by(rowid) %>% filter(n_distinct(tag) == 2, n_distinct(loc) == 1) %>% ungroup() %>% distinct(rowid, value) %>% left_join(dat, by = c("rowid", "value")) %>% select(-rowid)
内容的提问来源于stack exchange,提问作者vita_aquaticus
相关产品推荐
相关产品推荐

