【发布时间】:2016-06-30 13:17:22
【问题描述】:
我正在尝试将多个条件应用于 data.frame 的多个列,其中条件 i 应应用于列 i,即应用的条件取决于我所在的列。我有一个可行的解决方案,但它有两个主要缺点,它在大数据上可能很慢,因为它使用 for 循环,并且它需要两个输入向量“应用条件的列”和“要应用的条件”以相同的顺序。我设想了一个利用快速数据整理包功能的解决方案,例如dplyr, data.table 并且在参数向量元素的顺序方面更加灵活。一个例子应该清楚(这里的条件只是一个阈值测试,但在更大的问题中,它可能是一个涉及数据集变量的更复杂的布尔表达式)。
t <- structure(list(a = c(2L, 10L, 10L, 10L, 3L),
b = c(5L, 10L, 20L, 20L, 20L),
c = c(100L, 100L, 100L, 100L, 100L)),
.Names = c("a", "b", "c"),
class = "data.frame",
row.names = c(NA, -5L))
foo_threshold <-
function(data, cols, thresholds, condition_name){
df <- data.frame(matrix(ncol = length(cols), nrow = nrow(data)))
colnames(df) <- paste0(cols, "_", condition_name)
for (i in 1:length(cols)){
df[,i] <- ifelse(data[,i] > thresholds[i],T,F)
}
return(df)
}
foo_threshold(data = t, cols = c("a", "b"), thresholds = c(5, 18),
condition_name = "bigger_threshold")
我试图在 dplyr 链中解决它,但我未能正确传递参数向量,即如何明确他应该将条件 i 应用于第 i 列。下面是我要去的插图。它不起作用,它遗漏了一些要点,但我认为它说明了我正在努力实现的目标。请注意,这里假设条件位于 data.frame 中,其中列变量保存 col 名称,阈值是通过查找(dplyr 文件管理器 + 选择链)提取的。
foo_threshold <- function(data, cols, thresholds, cond_name) {
require(dplyr)
# fun to evaluate boolean condition
foo <- function(x) {
threshold <- thresholds %>% filter(variable==x) %>% select(threshold)
temp <- ifelse(x > threshold, T, F)
return(temp)
}
vars <- setNames(cols, paste0(cols,"_",cond_name))
df_out <-
data %>%
select_(.dots = cols) %>%
mutate_(funs(foo(.)), vars) %>%
select_(.dots = names(vars))
return(df_out)
}
# create threshold table
temp <-
data.frame(variable = c("a", "b"),
threshold = c(5, 18),
stringsAsFactors = F)
# call function (doesn't work)
foo_threshold(data = t, thresholds = temp, cond_name = "bigger_threshold")
编辑:@thepule data.frame of conditions 可能如下所示,其中 x 是列。所以每个条件都会针对其对应列的每一行进行评估。
conditions <-
data.frame(variable = c("a", "b"),
condition = c("x > 5 and x < 10", "!x %in% c("o", "p")"),
stringsAsFactors = F)
【问题讨论】:
-
我会提醒不要将对象命名为
t,因为那是转置函数 -
感谢您的提示。它应该代表 temp,我很懒。
-
好的,这种格式的条件肯定更棘手。不过有趣的问题。
-
好的,这种格式的条件肯定更棘手。不过有趣的问题。那里的“o”和“p”代表什么?
-
示例并不完美。想要明确布尔值不仅适用于数字变量,也适用于字符变量。当然,同时比较数字和字符值是没有意义的。