r - 根据应用于多列的规则识别要删除的行
问题描述
如果跨多个列的内容与不同的用户条件不匹配,我想从我的数据框中删除行。
以下代表应该涵盖我想要实现的复杂性。
install.packages("dplyr")
install.packages("purrr")
options(stringsAsFactors=FALSE)
# Create user criteria (UC) data.
UC <- data.frame(
Series = 1:5,
Unit = c("cm","mm",NA,NA,"cm"),
Month = c(NA,NA,"Jan",NA,"Feb"),
Height = c(3,NA,NA,3,1)
)
# Create range of scenarios (RS) but only consider two series initially.
set.seed(2)
num_series <- 2
RS <- data.frame(
Series = sample(c(1:5), num_series, replace=TRUE),
Unit = sample(c("cm","mm"), num_series, replace=TRUE),
Month = sample(c("Jan","Feb","Mar","Apr"), num_series, replace=TRUE),
Height = sample(c(1:3), num_series, replace=TRUE)
)
# Identify applicable critera for matching (AC).
AC <- dplyr::filter(UC, UC$Series %in% unique(RS$Series))
AC <- AC[, !purrr::map_lgl(AC, ~all(is.na(.))), drop=FALSE]
# Combine the scenario data and the applicable criteria.
SC <- merge(x=RS, y=AC, by="Series", all.x=TRUE)
# Function to identify rows for removal.
fn_remove_row <- function(cols, rm) {
x <- paste0(cols,".x")
y <- paste0(cols,".y")
rm$remove <- ifelse(rm$remove == 0 & !is.na(rm[[y]]) & rm[[y]] != rm[[x]], 1, rm$remove)
rm[[y]] <- NULL
setnames(rm, eval(substitute(x)), unlist(cols))
}
# Identify columns to be considered for matching for the given scenarios.
cols <- as.list(gsub("\\.y","",grep("\\.y", names(SC), value=TRUE)))
# Final dataframe (with option to filter).
SC$remove <- 0 # Initial values.
df <- cbind(data.frame(lapply(cols, fn_remove_row, rm=SC)))
#df <- dplyr::filter(df, remove == 0)
我的代码的一些解释:
• UC 数据框提供了一些示例规则,这些规则可能适用于也可能不适用于特定列,具体取决于数据中观察到的系列。
• RS 数据帧创建了需要满足的不同数据场景,尽管我最初只考虑了两种场景。num_series
可以增加该参数以提供更多场景。
• AC 数据框对用户标准进行子集化,以仅选择适用于观察到的场景的列。
• SC 数据框结合了场景数据和适用的标准。带有要应用规则的列将用.x
后缀(原始数据)和.y
后缀(标准)来标识。
• 我创建了一个函数来依次考虑所需的列并检查值是否匹配。如果它们不匹配,则该行将被标记为“1”以指示将其删除。如果特定列的条件值缺失 (NA),则在这种情况下无需进行匹配。进行检查后,删除条件列,并重命名原始数据列以删除后缀。
• 我lapply
用来创建包含要过滤的列的最终数据框(df)。当前未应用过滤器,因为未正确创建标志。
输入数据帧(使用种子 = 2 创建)是:
> UC > RS
Series Unit Month Height Series Unit Month Height
1 cm <NA> 3 1 mm Apr 1
2 mm <NA> NA 4 cm Apr 3
3 <NA> Jan NA
4 <NA> <NA> 3
5 cm Feb 1
由于 RS 包含系列 1 和 4,因此创建的 AC 也包含这些系列,并且仅包含仍然适用的列:
> AC
Series Unit Height
1 cm 3
4 <NA> 3
合并根据需要组合 RS 和 AC 并remove
初始化标志:
> SC
Series Unit.x Month Height.x Unit.y Height.y remove
1 mm Apr 1 cm 3 0
4 cm Apr 3 <NA> 3 0
在这种情况下,我想将系列 1 标记为删除,因为Unit.x
不等于Unit.y
,但如果它们匹配,它仍然会被标记,因为Height.x
不等于Height.y
。月份列没有进入等式,因为这两个系列没有适用的标准。
系列 4 不会被标记,因为 Unit 比较不适用 ( Unit.y
= NA
) 并且 Height 比较给出了匹配。
最后我想要(过滤之前):
> df
Series Unit Month Height remove
1 mm Apr 1 1
4 cm Apr 3 0
但是,尽管没有电话和各种未显示的尝试,但我从这些列中得到的lapply
是重复的列:return()
cbind
> df
Series Unit Month Height.x Height.y remove Series.1 Unit.x Month.1 Height Unit.y remove.1
1 mm Apr 1 3 1 1 mm Apr ...
循环通过适用列的功能是否lapply
错误,或者可以使其工作?对我来说,感觉就像缺少了一个微小的关键元素。
一个完整的解决方案测试应该使用不同的种子并增加num_series
。
解决方案
看来这是使用for-loop
而不是我们可信赖的lapply
朋友的好时机:
# Function to identify rows for removal.
fn_remove_row <- function(col, rm) {
x <- paste0(col,".x")
y <- paste0(col,".y")
rm$remove <- ifelse(rm$remove == 0 & !is.na(rm[[y]]) & rm[[y]] != rm[[x]], 1, rm$remove)
rm[[y]] <- NULL
setnames(rm, eval(substitute(x)), unlist(col))
return(rm)
}
# Identify columns to be considered for matching for the given scenarios.
cols <- c(gsub("\\.y","",grep("\\.y", names(SC), value=TRUE)))
# Final dataframe (with option to filter).
SC$remove <- 0 # Initial values.
for (i in 1:length(cols)) {
col <- cols[i]
SC <- fn_remove_row(col, SC)
}
推荐阅读
- c# - AADSTS500011 - PowerBi C# .NET(在租户 y 中找不到资源 x)
- arrays - 根据大小动态导入范围
- google-apps-script - 如何使用脚本在 Google 表格中打开文件 > 导入功能?
- java - 无法解析依赖 antlr:antlr:2.7.7
- scala - 返回类型分配给 RDD 的 val
- jenkins - Jenkins自定义消息而不是管道中的持续时间
- javascript - Axios 在单独的函数中返回未定义
- jsf - 在jsf中,如何在选择选项中换行(SelectOneMenu)
- arrays - 有没有办法将字符串数组拆分为 Bash 中的多个其他数组?
- java - java数组打印星号方块