使用expand.grid筛选数字组合时结果全为NA的问题排查
解决expand.grid筛选后结果全为NA的问题
问题背景
需要生成满足以下所有条件的6位数字组合:
- 每个组合恰好包含6个数字
- 可选数字仅为1、5、7
- 1之后只能跟1或5
- 5之后只能跟5或7
- 7之后只能跟7
- 组合中至少包含2个1
使用expand.grid生成所有组合后,添加验证列并筛选,结果却全为NA行。
错误原因
在执行apply(all_combinations, 1, ...)时,all_combinations中已经新增了starts_with_1等字符型列(值为"yes"/"no"),导致apply将整行转换为字符向量,后续diff(as.numeric(x))会因字符转数值失败产生NA,最终筛选时逻辑判断结果为NA,得到全NA行。
修正方案
仅针对数字列(Var1到Var6)进行条件验证,避免字符列干扰。以下是修正后的代码:
# 生成所有由1、5、7组成的6位组合 numbers <- c(1, 5, 7) all_combinations <- data.frame(expand.grid(rep(list(numbers), 6))) # 定义条件验证函数,仅处理数字行 check_valid <- function(row) { # 至少包含2个1 has_two_ones <- sum(row == 1) >= 2 # 序列非递减(对应规则3-5:1后只能1/5,5后只能5/7,7后只能7) is_non_decreasing <- all(diff(row) >= 0) # 组合以1开头(非递减+至少2个1的情况下,此条件其实是隐含成立的,可根据需求保留) starts_with_1 <- row[1] == 1 return(starts_with_1 & is_non_decreasing & has_two_ones) } # 筛选符合条件的组合 valid_combinations <- all_combinations[ apply(all_combinations[, paste0("Var", 1:6)], 1, check_valid), ] # 可选:添加验证列用于查看 valid_combinations$at_least_two_ones <- apply(valid_combinations[, 1:6], 1, function(x) sum(x == 1) >= 2) valid_combinations$non_decreasing <- apply(valid_combinations[, 1:6], 1, function(x) all(diff(x) >= 0)) valid_combinations$starts_with_1 <- valid_combinations$Var1 == 1 # 查看结果 valid_combinations
说明
- 非递减序列的特性恰好匹配规则3-5:因为1 < 5 < 7,所以后续数字只能大于等于当前数字,完全符合"1后只能1/5、5后只能5/7、7后只能7"的要求。
- 由于非递减序列中若存在1,所有1必然集中在最前端,因此
starts_with_1条件其实是has_two_ones+is_non_decreasing的隐含结果,可根据需求选择是否保留。 - 此方法保留了
expand.grid的灵活性,后续修改条件(如要求至少3个1)时,只需调整check_valid函数中的判断逻辑即可。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

