【问题标题】:How to nest tables in a column of a dataframe?如何在数据框的列中嵌套表?
【发布时间】:2021-09-06 04:03:34
【问题描述】:

我读到可以将数据帧存储在带有嵌套的数据帧的列中: https://tidyr.tidyverse.org/reference/nest.html

是否也可以将存储在数据框的列中?

原因是我想用 Caret 计算数据帧的每个子组的 Kappa。虽然 caret::confusionMatrix(t) 需要一个表格作为输入。

在下面的示例代码中,如果我一次计算完整数据帧的 Kappa,则可以正常工作:

library(tidyverse)
library(caret)

  # generate some sample data:
  n <- 100L
  x1 <- rnorm(n, 1.0, 2.0)
  x2 <- rnorm(n, -1.0, 0.5)
  y  <- rbinom(n, 1L, plogis(1 * x1 + 1 * x2))
  my_factor <- rep( c('A','B','C','D'), 25 )   
  
  df <- cbind(x1, x2, y, my_factor)
  
  # fit a model and make predictions:
  mod <- glm(y ~ x1 + x2, "binomial")
  probs <- predict(mod, type = "response")
  
  # confusion matrix
  probs_round <- round(probs)
  
  t <- table(factor(probs_round, c(1,0)), factor(y, c(1,0)))
  ccm <- caret::confusionMatrix(t)
  
  # extract Kappa:
  ccm$overall[2]

> Kappa
> 0.5232
  
  
  
  

尽管如果我尝试使用 group_by 为每个因子生成 Kappa 作为子组(请参见下面的代码),但它不会成功。我想我需要以某种方式将t 嵌套在df 中,尽管我不知道如何:

  # extract Kappa for every subgroup with same factor (NOT WORKING CODE):

  df <- cbind(df, probs_round)
  df <- as.data.frame(df)
  
  output <- df %>%
    dplyr::group_by(my_factor) %>% 
    dplyr::mutate(t = table(factor(probs_round, c(1,0)), factor(y, c(1,0)))) %>%
    summarise(caret::confusionMatrix(t))

Expected output:

>my_factor Kappa
>1 A       0.51
>2 B       0.52
>3 C       0.53
>4 D       0.54

这是正确的吗?这可能吗? (由于样本数据的随机性,Kappa 的确切值会有所不同)

非常感谢!

【问题讨论】:

  • 不清楚你想要什么,你能分享你的预期输出吗?此外,您下次可能想尝试使用reprex::reprex(),您的示例并非 100% 可重现。
  • @Dan Chaltiel 对不起,我已经修改了我上面的例子。

标签: r dplyr datatable nested r-caret


【解决方案1】:

上述方法最容易得到想要的结果。但只是为了展示什么是可能的,我们可以将您的方法与 rowwise::nest_by 一起使用,它将数据集 rowwise 分组。

在下面的方法中,我们为每个子组计算一个单独的glm。我不确定这是否是您想要做的。

library(tidyverse)
library(caret)


# generate some sample data:
n <- 1000L

df <- tibble(x1 = rnorm(n, 1.0, 2.0),
             x2 = rnorm(n, -1.0, 0.5),
             y = rbinom(n, 1L, plogis(x1 + 1 * x1 + 1 * x2)),
             my_factor = rep( c('A','B','C','D'), 250))

output <- df %>%
  nest_by(my_factor) %>%
  mutate(y = list(data$y), 
         mod = list(glm(y ~ x1 + x2,
                        family = "binomial",
                        data = data)),
         probs = list(predict(mod, type = "response")),
         probs_round = list(round(probs)),
         t = list(table(factor(probs_round, c(1, 0)),
                  factor(y, c(1, 0)))),
         ccm = caret::confusionMatrix(t)$overall[2])

output %>%

  pull(ccm)
#>     Kappa     Kappa     Kappa     Kappa 
#> 0.7743682 0.7078112 0.7157761 0.7549340

reprex package (v0.3.0) 于 2021 年 6 月 23 日创建

【讨论】:

  • @TimTeaFan 在我的数据中,我有一个因子变量,它不会提高我模型的 AUC,尽管我曾期望它会。出于这个原因,我尝试通过这个因子变量对几个指标进行分组,以查看因子值之间的指标是否有任何差异。虽然我不知道这是否有意义。对于每个因子值,我也会尝试使用您的方法以及特定模型。谢谢!
  • @user2165379:如果您的因素变量与您的结果变量不相关,则无需对您的指标进行分组,甚至无需为每个组计算单独的模型。如果您使用rnorm 生成随机数据,那么这两种方法都会导致相似的结果。使用一个回归并对指标进行分组是一种验证检查,以查看您的方法在某些组中的表现是更好还是更差(如果与rnorm 一起使用则毫无意义)。如果您为每个组计算一个单独的模型,那么您基本上是在测试分组变量和自变量之间的交互。
  • @TimTeaFan,上面的 rnorm 数据仅作为 group_by 问题的示例。如果我在我的真实数据中拟合一个具有真实因素的模型,则 AUC 没有任何改善。接下来,我在没有这个因子变量的情况下拟合了模型,之后我用这个因子分组并计算了几个指标,看看这些组之间的指标是否存在差异。我这样做的原因是查看因子变量中是否可能存在某些信号(如果这些组之间的结果存在差异)。或者这没有任何意义?
【解决方案2】:

您可以跳过给您带来麻烦的中间mutate()

library(dplyr)
library(caret)

df %>%
    group_by(my_factor) %>% 
    summarize(t = confusionMatrix(table(factor(probs_round, c(1,0)),
                                        factor(y, c(1,0))))$overall[2])

返回:

# A tibble: 4 x 2
  my_factor     t
  <chr>     <dbl>
1 A         0.270
2 B         0.513
3 C         0.839
4 D         0.555

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多