2015-04-27 3 views
1

Я ищу решение для применения функции confusionMatrix() от {caret} к определенным элементам разделенного списка. У меня есть 3 группы, каждая группа имеет 10 наблюдений столбцов Actuals и 3 Preds.Применить confusionMatrix() к элементам разделенного списка в R

library(caret) 
set.seed(10) 
dat <- data.frame(Group = c(rep(1, 10), rep(2, 10), rep(3, 10)), Actual = round(runif(30, 0, 1)), 
       Preds1 = round(runif(30, 0, 1)), Preds2 = round(runif(30, 0, 1)), Preds3 = round(runif(30, 0, 1))) 

> dat 
    Group Actual Preds1 Preds2 Preds3 
1  1  1  1  0  0 
2  1  0  0  0  1 
3  1  0  0  0  1 
4  1  1  1  0  1 
........... 
27  3  1  0  1  0 
28  3  0  0  0  1 
29  3  1  0  0  1 
30  3  0  1  0  1 

Окончательное решение должно создавать матрицы смешения по группам по каждой колонке Preds. Мне понадобятся реальные таблицы таблиц путаницы, но в конечном итоге вам нужно будет извлечь элементы $ general и $ byClass и в итоге получить что-то вроде ниже.

> conf_matrix 
$Preds1 
     Accuracy Sensitivity Specificity 
[1,] 0.73  0.8   0.6    
[2,] 0.93  0.91   1    
[3,] 0.87  0.83   1    
[4,] 0.8  0.82   0.75 
............... 
[27,] 0.8  0.82   0.75   
[28,] 0.58  0.67   0.5    
[29,] 1   0.67   1    
[30,] 1   0   1 

$Preds2 
     Accuracy Sensitivity Specificity 
[1,] 0.73  0.8   0.6    
[2,] 0.93  0.91   1    
[3,] 0.87  0.83   1    
[4,] 0.8  0.82   0.75  
............... 
[27,] 0.8  0.82   0.75   
[28,] 0.58  0.67   0.5    
[29,] 1   0.67   1    
[30,] 1   0   1 

$Preds3 
............... 

Я попытался сценарий ниже, но сохраняющий нарваться проблемами при попытке вторичного индексирования столбца Preds в каждой группе. Я считаю, что это имеет какое-то отношение к моим вложенным lapply's и тому, как я индексирую, поскольку это работает, когда я разлагаю код и прохожу через него по одному.

Я также попытался сделать это вручную, используя таблицу(), однако отказался от этого метода, потому что он не дает мне согласованных результатов, например, с помощью confusionMatrix().

lapply(seq_along(split(dat[3:5], list(dat$Group))), function(x) { 
    x_temp <- split(dat[3:5], list(dat$Group))[[x]] 
    lapply(seq_along(x_temp), function(x2) { 
     x_temp <- x_temp[[x2]] 
     lapply(seq_along(split(dat[2], list(dat$Group))), function(y) { 
      y_temp <- split(dat[2], list(dat$Group))[[y]] 
      lapply(seq_along(y_temp), function(y2) { 
       y_temp <- y_temp[[y2]] 
       confusionMatrix(x_temp, y_temp) 
      }) 
     }) 
    }) 
}) 

Я могу быть в стороне от базы, поэтому я открыт для всех предложений и комментариев.

ответ

1

Я не понимаю конечный результат, но матрицы смешения будут получены следующим образом.

library(caret) 
set.seed(10) 
dat <- data.frame(Group = c(rep(1, 10), rep(2, 10), rep(3, 10)), Actual = round(runif(30, 0, 1)), 
        Preds1 = round(runif(30, 0, 1)), Preds2 = round(runif(30, 0, 1)), Preds3 = round(runif(30, 0, 1))) 
dat[] <- lapply(dat, as.factor) 

# split by group 
dats <- split(dat[,-1], dat$Group) 

cm <- do.call(c, lapply(dats, function(x) { 
    actual <- x[, 1] 
    lapply(x[, 2:4], function(y) { 
    confusionMatrix(actual, unlist(y))$table 
    }) 
})) 
cm[1:3] 
$`1.Preds1` 
Reference 
Prediction 0 1 
0 3 4 
1 0 3 

$`1.Preds2` 
Reference 
Prediction 0 1 
0 4 3 
1 3 0 

$`1.Preds3` 
Reference 
Prediction 0 1 
0 3 4 
1 1 2 

@ Brian

В ссылке (What's the difference between lapply and do.call in R?), я нахожу ответ Пола Hiemstra довольно просто.

- lapply похоже на map, do.call нет. lapply применяет функцию ко всем элементам списка, do.call вызывает функцию, где все аргументы функции находятся в списке. Итак, для списка элементов nlapply имеет n вызовы функций, а do.call имеет только one вызов функции. Таким образом, do.call сильно отличается от lapply.

В примере,

dats состоит из трех элементов - 1, 2 и 3

dats <- split(dat[,-1], dat$Group) 
dats[1] 
$`1` 
Actual Preds1 Preds2 Preds3 
1  1  1  0  0 
2  0  0  0  1 
3  0  0  0  1 
4  1  1  0  1 
5  0  0  1  0 
6  0  1  1  1 
7  0  1  1  0 
8  0  1  0  1 
9  1  1  0  1 
10  0  1  0  0 

Ниже двойной петли и первый цикл применяется к 1, 2 и 3, а второй контур, чтобы Preds1 , Preds2 и Preds3. Поэтому список, сгенерированный только lapply(), создает вложенный список, как показано ниже.

lapply(dats, function(x) { 
    actual <- x[, 1] 
    lapply(x[, 2:4], function(y) { 
    confusionMatrix(actual, unlist(y))$table 
    }) 
})[1] 
$`1` 
$`1`$Preds1 
Reference 
Prediction 0 1 
0 3 4 
1 0 3 

$`1`$Preds2 
Reference 
Prediction 0 1 
0 4 3 
1 3 0 

$`1`$Preds3 
Reference 
Prediction 0 1 
0 3 4 
1 1 2 

Однако вышеизложенное нелегко использовать позже, поскольку для доступа к каждой матрице путаницы необходим другой двойной цикл. Он упрощен с do.call(). Первым аргументом c является функция и так, чтобы структура была уменьшена, чтобы быть доступной одним контуром. Обычно я предпочитаю использовать do.call(), когда необходимо изменить структуру списка.

do.call(c, lapply(dats, function(x) { 
    actual <- x[, 1] 
    lapply(x[, 2:4], function(y) { 
    confusionMatrix(actual, unlist(y))$table 
    }) 
}))[1:3] 
$`1.Preds1` 
Reference 
Prediction 0 1 
0 3 4 
1 0 3 

$`1.Preds2` 
Reference 
Prediction 0 1 
0 4 3 
1 3 0 

$`1.Preds3` 
Reference 
Prediction 0 1 
0 3 4 
1 1 2 
+0

@ Jaehyeon Kim Гораздо менее сложна, чем моя попытка выше. Спасибо. Моим конечным результатом являются отдельные элементы confusionMatrix(). В вашем решении перечислены элементы таблицы $ table, которые мне нужны, но мне также нужно извлечь $ general [1] и $ byClass [1: 2], что даст мне точность, чувствительность и специфичность. Я могу соответствующим образом обновить ваш код. – Brian

+0

@ Jaehyeon Kim Я читал о do.call http://stackoverflow.com/questions/10801750/whats-the-difference-between-lapply-and-do-call-in-r, однако немного неясно, как когда я должен выбрать этот метод над чем-то вроде моих вложенных циклов выше. Не могли бы вы объяснить, почему это лучший вариант? – Brian

+0

@ Jaehyeon Kim Очень хорошо объяснил и решает мою проблему. Благодарю. Я считаю, что двойной цикл - это то, где я сталкивался с моими проблемами, требующими извлечь из нескольких уровней в списке. – Brian

Смежные вопросы