实现按行筛选最小唯一值数量的自定义R函数
实现按行筛选最小唯一值数量的自定义R函数
嘿,我懂你想要的功能啦——就是要从你的tibble里筛选出那些至少有指定数量(min_distinct)不同列值的行,对吧?毕竟你的数据大部分行已经是唯一的,但你想进一步控制每行的多样化程度。下面就来一步步实现这个自定义函数,还会结合你的测试数据来演示~
思路说明
核心逻辑很简单:对每一行计算其所有列中唯一值的数量,然后保留那些数量≥min_distinct的行。我们可以用tidyverse风格或者base R风格来实现,两种方式都给你列出来~
方式一:Tidyverse风格(贴合dplyr习惯)
如果你平时常用dplyr,这个版本的函数会更符合你的使用习惯:
library(dplyr) new_function_n_uniques <- function(data, min_distinct) { data %>% rowwise() %>% # 开启按行处理模式 filter(n_distinct(c_across(everything())) >= min_distinct) %>% # 计算每行唯一值数量并筛选 ungroup() # 取消按行分组,恢复正常tibble结构 }
代码解释
rowwise():让后续的操作按每一行独立执行c_across(everything()):获取当前行的所有列值,形成一个向量n_distinct():计算这个向量里唯一值的数量filter():只保留唯一值数量≥min_distinct的行ungroup():处理完后取消按行分组,避免后续操作受影响
方式二:Base R风格(更高效)
如果你的数据量很大(比如远超10k行),base R的版本速度会更快,因为避免了rowwise的分组开销:
new_function_n_uniques_base <- function(data, min_distinct) { # 计算每行的唯一值数量 row_unique_counts <- apply(data, 1, function(row) length(unique(row))) # 筛选出符合条件的行 data[row_unique_counts >= min_distinct, ] }
代码解释
apply(data, 1, ...):按行遍历数据框,对每一行执行后面的函数length(unique(row)):计算当前行的唯一值数量- 最后用布尔向量筛选出满足条件的行
测试使用
用你的测试数据来演示怎么用:
# 先读取测试数据 data <- readr::read_csv("https://gist.githubusercontent.com/NateNohling/b5bd04eda864c135e1bbfa86a09a4295/raw/116f97ef2d2a1bdb0c10d493fceab1166f5a3065/test.csv") # 用tidyverse版本筛选至少有3个不同值的行 filtered_data <- new_function_n_uniques(data, 3) # 或者用base R版本 filtered_data_base <- new_function_n_uniques_base(data, 3)
额外小提示
如果你的数据里有NA值,默认情况下unique()和n_distinct()都会把NA当作一个唯一值。如果你想忽略NA的话,可以修改代码:
- Tidyverse版本:把
n_distinct(c_across(everything()))改成n_distinct(c_across(everything()), na.rm = TRUE) - Base R版本:把
length(unique(row))改成length(unique(na.omit(row)))
备注:内容来源于stack exchange,提问作者NateN
相关产品推荐
相关产品推荐

