我想做类似嵌入式循环的事情,但是使用应用函数,其目标是在进入程序的下一部分之前检查各种条件。
我有两个对象,一个产品描述列表,可以按如下方式创建:
test_products <- list(c("dingdong","small","affordable","polished"),c("wingding","medium","cheap","dull"),c("doodad","big","expensive","shiny"))
不允许的功能组合的数据框,其中每行代表不允许的功能组合。可以按如下方式创建示例数据框:
disallowed <- data.frame(trait1 = c("dingdong","wingding","doodad"),
trait2 = c("medium","big","big"),
stringsAsFactors = FALSE)
我的目标是尽可能有效地针对每个不允许的组合检查每个产品。到目前为止,我可以针对所有禁令查看一个产品,如下所示(在这种情况下,第三个产品):
apply(disallowed, 1, function(x) x %in% unlist(test_products[[3]]))
或者我可以针对一种不允许的特征组合(第三种组合)检查所有产品。
lapply(test_products, function(x) disallowed[3,] %in% x)
是否可以在不使用循环的情况下针对不允许的要素组合的数据框的所有行检查所有产品?
我的最终结果应该是这样的:
Product 1: OK
Product 2: OK
Product 3: NOT OK
由于产品3与第三个不允许的行相撞。
答案 0 :(得分:1)
肯定有更多优雅的方式,但我将分享我对此的看法。
首先,您创建disallowed
数据框的方式是错综复杂的。我决定使用以下代码创建disallowed
。
# Create a data frame showing disallowed traits
disallowed <- data.frame(trait1 = c("dingdong","wingding","doodad"),
trait2 = c("medium","big","big"),
stringsAsFactors = FALSE)
然后我创建了一个名为violate
的函数,它有两个参数。第一个参数product
是一个字符向量。第二个参数check_df
是数据框包含不允许的特征。
violate
的输出是逻辑向量。 TRUE
表示该行的check_df
中的所有两个特征都是TRUE
。
# Create the violate function
violate <- function(product, check_df){
temp_df <- as.data.frame(lapply(check_df, function(Col) Col %in% product))
temp_vec <- apply(temp_df, 1, function(Row) sum(Row) == 2)
return(temp_vec)
}
# Test the violate function
violate(test_products[[3]], check_df = disallowed)
# [1] FALSE FALSE TRUE
之后,我通过violate
列表使用sapply
应用了test_products
函数。对violate
的结果进行了评估,以查看所有不允许的检查是否为FALSE
# Apply the violate function and check if all results from violate is FALSE
sapply(test_products, function(product){
sum(violate(product, check_df = disallowed)) == 0})
# [1] TRUE TRUE FALSE
如您所见,结果的第三个元素是FALSE
,表示第三个产品不正常,而产品1和产品2都可以,因为sapply
的最终结果都是TRUE
。