如何筛选DataFrame中每行严格单调递增的行(支持动态列数)
筛选DataFrame中列值严格递增的行(支持动态列数)
问题描述
现有如下结构的DataFrame:
# 示例数据 library(tibble) df <- tibble( COL_1 = c(1,1,1,1,1,1,1,1,1,1), COL_2 = c(1,1,1,1,2,1,3,1,1,3), COL_3 = c(1,1,1,1,1,1,4,1,9,5), COL_4 = c(1,1,1,1,1,1,5,1,1,7), COL_5 = c(1,1,1,1,1,1,6,1,1,9), COL_6 = c(1,2,3,4,5,6,7,8,9,10) )
需要筛选出COL_1到COL_N(N为动态列数)中值严格递增的行,最终结果仅保留第7、10行:
# 预期结果 # # A tibble: 2 × 6 # COL_1 COL_2 COL_3 COL_4 COL_5 COL_6 # <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> # 1 1 3 4 5 6 7 # 2 1 3 5 7 9 10
要求代码支持动态列数,不能用硬编码的filter(COL_6 > COL_5 & ... & COL_2 > COL_1)形式。
解决方案
方法1:使用dplyr(tidyverse风格)
通过rowwise()逐行处理,结合c_across()提取动态列,再用diff()检查递增性:
library(dplyr) # 1. 动态匹配并排序列名(确保按COL_1、COL_2...COL_N的顺序) col_names <- grep("^COL_\\d+$", names(df), value = TRUE) col_names <- sort(col_names, key = function(x) as.integer(sub("COL_", "", x))) # 2. 筛选严格递增的行 filtered_df <- df %>% rowwise() %>% filter(all(diff(c_across(all_of(col_names))) > 0)) %>% ungroup() # 查看结果 filtered_df
方法2:使用base R(轻量高效)
用apply()按行遍历,直接检查每行的差值是否全为正:
# 1. 动态匹配并排序列名 col_names <- sort(grep("^COL_\\d+$", names(df), value = TRUE), key = function(x) as.integer(sub("COL_", "", x))) # 2. 筛选行 filtered_df <- df[apply(df[col_names], 1, function(row) all(diff(row) > 0)), ] # 查看结果 filtered_df
说明
两种方法均支持任意数量的COL_*列:
- 通过
grep匹配所有符合COL_数字格式的列名 - 用
sort结合自定义key确保列按数字顺序排列(避免列名乱序导致判断错误) - 核心逻辑是计算每行相邻列值的差值,验证所有差值均大于0,以此判断是否严格递增
内容的提问来源于stack exchange,提问作者Rgrvkfer
相关产品推荐
相关产品推荐

