[英]Error in generalized linear mixed model cross-validation: The value in 'data[[cat_col]]' must be constant within each ID
我正在尝试使用 groupdata2 和 cvms 包对广义线性混合 model 进行 5 折交叉验证。 这是我尝试运行的代码:
data <- groupdata2::fold(detect, k = 5,
cat_col = 'outcome',
id_col = 'bird') %>%
arrange(.folds)
cvms::cross_validate(
data,
"outcome ~ sex + year + season + (1 | bird) + (1 | obsname)",
family="binomial",
fold_cols = ".folds",
control = NULL,
REML = FALSE)
这是我收到的错误:
Error in groupdata2::fold(detect, k = 4, cat_col = "outcome", id_col = "bird") %>% :
1 assertions failed:
* The value in 'data[[cat_col]]' must be constant within each ID.
在 package 小插图中,给出了以下解释:“参与者在整个数据集中必须始终具有相同的诊断('a' 或 'b')。否则,参与者可能被置于多个折叠中。” 这在示例中是有意义的。 但是,我的数据是基于重新观察鸟类的结果,因此结果会根据是否在特定调查中观察到鸟类而有所不同。 有没有解决的办法?
可重现的例子:
bird <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3)
outcome <- c(0,1,1,1,0,0,0,1,0,1,0,1,0,0,1)
df <- data.frame(bird, outcome)
df$outcome <- as.factor(df$outcome)
df$bird <- as.factor(df$bird)
data <- groupdata2::fold(df, k = 5,
cat_col = 'outcome',
id_col = 'bird') %>%
arrange(.folds)
完整的文档说:
cat_col
:用于在折叠之间平衡的分类变量的名称。 例如,在预测二元变量(a 或 b)时,我们通常希望在每个折叠中都表示两个类。 注意如果还传递了“id_col
”,则“cat_col
”应该在每个 ID 中保持不变。
因此,在这种情况下,如果个别鸟类 ( id_col
) 内的结果不同,您根本无法指定折叠在结果方面是平衡的。 (我不是 100% 理解软件中的这种限制:似乎应该可以通过选择具有平衡结果范围的组(鸟)来至少进行近似平衡,但我可以看到它如何进行平衡程序更难)。
不过,在我看来,平衡结果的重要性总体上被高估了。 缺乏平衡意味着?binomial_metrics
中的一些更简单的指标(例如准确度、灵敏度、特异性)不是很有用,但其他的(平衡准确度、AUC、aic)应该没问题。
一个潜在的更大问题是您似乎(可能)具有交叉随机效应(即(1|bird) + (1|obsname)
)。 我猜obsname
是观察者的名字:如果一些观察者检测到(或未能检测到)多只鸟,而一些鸟被多个观察者检测到/失败,那么可能无法定义实际上独立的折叠,或者至少这可能非常困难。
您可以在 groupdata2 v2.0.0 中使用新的collapse_groups()
groupdata2 v2.0.0
而不是fold()
。 它允许您采用现有组(例如bird
)并将它们折叠到更少的组(例如折叠),并尝试平衡多个分类列、数字列和因子列(唯一级别的数量 - 尽管相同的级别可能在多个组中)。
它没有fold()
关于改变结果的约束,但另一方面,在“不变的结果”上下文中没有相同的“保证”。 例如,它不保证所有折叠中的每个结果级别中的至少一个。
你需要的鸟比折叠的数量多,所以我在测试数据中添加了一些:
bird <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,
4,4,4,5,5,5,5,5,6,6,6,6,6,7,7,7,7)
outcome <- c(0,1,1,1,0,0,0,1,0,1,0,1,0,0,1,0,1,
0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1,1)
df <- data.frame(bird, outcome)
df$outcome <- as.factor(df$outcome)
df$bird <- as.factor(df$bird)
# Combine 'bird' groups to folds
data <- groupdata2::collapse_groups(
data = df,
n = 3,
group_cols="bird",
cat_col="outcome",
col_name = ".folds"
) %>%
arrange(.folds)
# Check the balance of the relevant columns
groupdata2::summarize_balances(
data=data,
group_cols=".folds",
cat_cols="outcome"
)$Groups
> # A tibble: 3 × 6
> .group_col .group `# rows` `# bird` `# outc_0` `# outc_1`
> <fct> <fct> <int> <int> <dbl> <dbl>
> 1 .folds 1 14 3 7 7
> 2 .folds 2 10 2 6 4
> 3 .folds 3 10 2 4 6
summarize_balances()
向我们展示了我们创建了 3 个折叠,第一个折叠有 14 行,其他折叠有 10 行。 在第一个折叠中有 3 个独特的鸟类级别,在其他折叠中有 2 个(通常只在组内唯一,但在这里我们知道鸟类只在一个组中,因为collapse_groups()
与它的group_cols
参数一起工作)。 结果变量(此处# outc_0
和# outc_1
)有些平衡。
对于较大的数据集,您可能希望运行多个折叠并从摘要中选择具有最佳平衡的一个。 这可以通过将num_new_group_cols = 10
添加到collapse_groups()
来完成(为了获得更好的结果,请启用auto_tune
设置),然后在运行summarize_balances()
时列出所有创建的组列。
希望这可以帮助您或其他类似 position 的人。 fold()
中的约束很难用其当前的内部方法解决,但collapse_groups
希望在这些情况下能解决问题。
查看更多https://rdrr.io/cran/groupdata2/man/collapse_groups.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.