繁体   English   中英

广义线性混合 model 交叉验证中的错误:“data[[cat_col]]”中的值必须在每个 ID 内保持不变

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM