Как я могу извлечь вектор на основе группы для передачи функции в суммировании или мутировании dplyr?

#r #tidyverse #dplyr #summarize

#r #tidyverse #dplyr #суммировать

Вопрос:

Я пытаюсь создать сводную таблицу точности, чувствительности и специфичности, используя AUC функцию в psych пакете. Я хотел бы определить входной вектор (t, вектор 4 x 1) для каждого уровня сгруппированной переменной.

То, что я пробовал, похоже, игнорирует группировку.

Пример:

 library(tidyverse)
library(psych)

Data <- data.frame(Class = c("A","B","C","D"),
                   TP = c(198,185,221,192),
                   FP = c(1,1,6,1),
                   FN = c(42,55,19,48),
                   TN = c(569,570,564,569))

Data %>% 
  group_by(Class) %>%
  mutate(Accuracy = AUC(t = unlist(.[1,2:5], use.names=FALSE))$Accuracy,
         Sensitivity = AUC(t = unlist(.[1,2:5], use.names=FALSE))$Sensitivity,
         Specificity = AUC(t = unlist(.[1,2:5], use.names=FALSE))$Specificity)
  

Это дает мне близкий к правильному результат, за исключением того, что значения точности, чувствительности и специфичности вычисляются только с первой строкой, а затем повторяются:

 # A tibble: 4 x 8
# Groups:   Class [4]
  Class    TP    FP    FN    TN Accuracy Sensitivity Specificity
  <fct> <dbl> <dbl> <dbl> <dbl>    <dbl>       <dbl>       <dbl>
1 A       198     1    42   569    0.947       0.995       0.931
2 B       185     0    55   570    0.947       0.995       0.931
3 C       221     6    19   564    0.947       0.995       0.931
4 D       192     1    48   569    0.947       0.995       0.931
  

Я также пытался с summarize :

 Data %>% 
  group_by(Class) %>%
  summarize(Accuracy = AUC(t = unlist(.[1,2:5], use.names=FALSE))$Accuracy,
         Sensitivity = AUC(t = unlist(.[1,2:5], use.names=FALSE))$Sensitivity,
         Specificity = AUC(t = unlist(.[1,2:5], use.names=FALSE))$Specificity)
  

Но результат такой же, как указано выше.

Желаемый результат — это уникальное вычисление для каждого уровня «Класса»

 # A tibble: 4 x 8
  Class    TP    FP    FN    TN Accuracy Sensitivity Specificity
  <fct> <dbl> <dbl> <dbl> <dbl>    <dbl>       <dbl>       <dbl>
1 A       198     1    42   569     0.95        0.99        0.93
2 B       185     0    55   570     0.93        0.99        0.91
3 C       221     6    19   564     0.97        0.97        0.97
4 D       192     1    48   569     0.94        0.99        0.92
  

Как мне вызвать функцию в summary или mutate для сохранения групп?

Ответ №1:

Это работает

 Data %>% 
  group_by(Class) %>%
  mutate(Accuracy = AUC(t = unlist(.[Class,2:5], use.names=FALSE))$Accuracy,
         Sensitivity = AUC(t = unlist(.[Class,2:5], use.names=FALSE))$Sensitivity,
         Specificity = AUC(t = unlist(.[Class,2:5], use.names=FALSE))$Specificity)
  

но, может быть, это более понятно

 Data %>% 
  group_by(Class) %>%
  mutate(Accuracy = AUC(t = c(TP, FP, FN, TN))$Accuracy,
         Sensitivity = AUC(t = c(TP, FP, FN, TN))$Sensitivity,
         Specificity = AUC(t = c(TP, FP, FN, TN))$Specificity)
  

Ответ №2:

Чтобы избежать вызова AUC несколько раз для каждого класса, я бы написал оболочку, например, так:

 # Load libraries
library(tidyverse)
library(psych)

# Create data frame
Data <- data.frame(Class = c("A","B","C","D"),
                   TP = c(198,185,221,192),
                   FP = c(1,1,6,1),
                   FN = c(42,55,19,48),
                   TN = c(569,570,564,569))

# Wrapper function
AUC_wrapper <- function(Class, TP, FP, FN, TN){
  res <- AUC(t = c(TP, FP, FN, TN))
  data.frame(Class = Class, 
             TP = TP,
             FP = FP,
             FN = FN,
             TN = TN,
             Accuracy = res$Accuracy, 
             Sensitivity = res$Sensitivity, 
             Specificity = res$Specificity)
}

# Run using purrr
pmap_dfr(Data, AUC_wrapper)

#   Class  TP FP FN  TN  Accuracy Sensitivity Specificity
# 1     A 198  1 42 569 0.9469136   0.9949749   0.9312602
# 2     B 185  1 55 570 0.9309494   0.9946237   0.9120000
# 3     C 221  6 19 564 0.9691358   0.9735683   0.9674099
# 4     D 192  1 48 569 0.9395062   0.9948187   0.9222042
  

Комментарии:

1. Это приводит к удалению Class имен и уровней выходных коэффициентов для меня