如何根据指定列表按顺序提取DataFrame对应行(含重复值匹配)
从R数据框中按指定顺序和重复次数提取匹配行
我从某个数据框的一列清理出了列表x,现在需要从原始数据框b中提取与x完全匹配(包括元素顺序、重复次数)的整行数据。
示例中的列表和数据框如下:
x = c(1,2,3,4,2,1,3) b <- data.frame( y = c(1,2,3,4,5,6,2,1,3,5,2,1), z = c("a","s","d","f","g","h","j","k","l","z","x","c") )
原始数据框b的内容:
y z 1 1 a 2 2 s 3 3 d 4 4 f 5 5 g 6 6 h 7 2 j 8 1 k 9 3 l 10 5 z 11 2 x 12 1 c
我期望得到的目标数据框是:
y z 1 1 a 2 2 s 3 3 d 4 4 f 5 2 j 6 1 k 7 3 l
但用b1<-subset(b, (y %in% x))得到的结果包含多余的行(第11、12行),请问该如何获取符合要求的数据框?(顺序很重要)
解决方案
方法1:循环追踪匹配位置
核心思路是按x的顺序,依次在b$y中找到未被匹配过的对应元素,记录行号:
# 初始化位置追踪变量 current_pos <- 1 row_indices <- integer(length(x)) for (i in seq_along(x)) { # 从current_pos开始查找第一个匹配的元素 match_pos <- which(b$y[current_pos:length(b$y)] == x[i])[1] # 转换为原始数据框的行号 row_indices[i] <- current_pos + match_pos - 1 # 更新下一次查找的起始位置 current_pos <- row_indices[i] + 1 } # 提取目标行 result <- b[row_indices, ]
方法2:使用dplyr管道式操作
如果习惯用dplyr工具链,可以用以下方式实现:
library(dplyr) library(purrr) # 给原始数据框添加行号列 b_with_id <- b %>% mutate(row_id = row_number()) # 按x的顺序依次匹配未被选中的行 match_result <- purrr::reduce( x, .init = list(last_row = 0, selected_rows = c()), function(state, val) { target_row <- b_with_id %>% filter(row_id > state$last_row, y == val) %>% slice(1) list( last_row = target_row$row_id, selected_rows = c(state$selected_rows, target_row$row_id) ) } ) # 提取最终结果 result <- b[match_result$selected_rows, ]
这两种方法都能严格按照x的顺序和重复次数提取对应行,避免%in%操作带来的多余匹配问题。
内容的提问来源于stack exchange,提问作者cc Li
相关产品推荐
相关产品推荐

