如何在R中同时对多变量按不同条件过滤(剔除各数值变量前1%)
剔除数据框中数值变量前1%数据的多种实现方法
需求:从数据框中剔除每个数值变量的前1%观测(即保留所有数值变量值小于自身99分位数的行),以下是用dplyr、data.table、基础R的几种实现方式。
首先定义原始数据并计算各数值变量的99分位数:
library(dplyr) df <- data.frame( var_1 = seq(1,10,1), var_2 = -seq(1,100,10), var_3 = seq(-5,4,1), var_4 = seq(5500,55000,10000), var_5 = rep(c("text 1","text 2", "text 3","text 4","text 5"),2) ) # 计算各数值变量的99分位数 top_one_percent <- sapply(select_if(df, is.numeric), quantile, .99)
1. dplyr 实现(推荐,简洁高效)
利用filter()结合across()一次性处理所有数值变量,无需多次嵌套filter:
df %>% filter(across(where(is.numeric), ~ .x < quantile(.x, 0.99)))
where(is.numeric):选中数据框中所有数值类型的列~ .x < quantile(.x, 0.99):对每个选中的列,判断其值是否小于自身的99分位数- 最终只保留所有数值变量都满足条件的行
2. data.table 实现
适合处理大型数据集,运行效率更高:
library(data.table) dt <- as.data.table(df) # 筛选数值列名 num_cols <- names(dt)[sapply(dt, is.numeric)] # 执行过滤 dt[dt[, Reduce(`&`, lapply(.SD, function(x) x < quantile(x, 0.99))), .SDcols = num_cols]]
.SDcols = num_cols:指定仅处理数值列lapply(.SD, ...):对每个数值列生成逻辑向量(是否小于99分位数)Reduce(&, ...):将多个逻辑向量合并为一个,只有所有条件都为TRUE时才保留该行
3. 基础R循环实现
逻辑直观,适合新手理解逐列过滤的过程:
# 获取所有数值列名 num_cols <- names(df)[sapply(df, is.numeric)] # 初始化结果为原数据框 filtered_df <- df # 循环遍历每个数值列,逐步过滤 for(col in num_cols) { # 计算当前列的99分位数 q_val <- quantile(filtered_df[[col]], 0.99) # 过滤掉大于等于分位数的行 filtered_df <- filtered_df[filtered_df[[col]] < q_val, ] } # 查看结果 filtered_df
4. 基础R向量化实现
无需循环,利用矩阵运算批量处理:
num_cols <- names(df)[sapply(df, is.numeric)] # 生成逻辑矩阵:每一行对应原数据的行,每一列对应数值列的判断结果 logic_matrix <- sapply(df[num_cols], function(x) x < quantile(x, 0.99)) # 保留所有列都为TRUE的行(即所有数值变量都满足条件) filtered_df <- df[rowSums(logic_matrix) == ncol(logic_matrix), ] filtered_df
rowSums(logic_matrix) == ncol(logic_matrix):判断每行的所有逻辑值是否都为TRUE
内容的提问来源于stack exchange,提问作者EW1982
相关产品推荐
相关产品推荐

