R: Извлечение элементов для цикла из объекта lapply - PullRequest
0 голосов
/ 10 ноября 2018

Вкратце: есть ли способ перебрать каждый элемент объекта lapply, описанный ниже allModelsResults?

Значение, например, allModelsResults$'1' дает мне 1-й элемент от объекта. Далее allModelsResults$'2' будет вторым элементом. Я хотел бы создать цикл for, чтобы извлечь каждый элемент, выполнить несколько команд и сохранить результаты.

Подробное описание ниже ...

У меня есть следующий код, где я запускаю простую модель ML, используя «knn» для нескольких спецификаций модели. Спецификации модели хранятся в allModelList, а все результаты хранятся в allModelsResults.

Одна модель из всего списка моделей выглядит так:

y ~ x1 + x2 + x3

или

y ~ x1 + x5 + x4

и т. Д. ... вкратце серия комбинаций спецификаций моделей

allModelsResults <- lapply(allModelsList, function(x) train(x,       data=All_categories_merged_done,method = "knn"))

Теперь я бы хотел извлечь каждый элемент (результаты каждой модели) один за другим, чтобы выполнить анализ. Например, я могу взять вручную:

allModelsResults$'1' для получения результатов из первой модели или allModelsResults$'5' для получения результатов из 5-й модели и т. Д.

В идеале я бы проходил через них в цикле for, где каждый раз, когда я выбираю один из элементов, запускается серия команд.

Любая помощь в том, как извлечь элементы из объекта allModelsResults, действительно поможет! У меня около 50 спецификаций моделей, поэтому мне нужно создать цикл или что-то подобное для автоматического извлечения одного за другим.

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

В качестве примера я извлекаю модель 1 здесь (очевидно, это не работает):

aggregate_results <- NULL

for(z in 1:length(categories)){
element_number_ID <- (element_number[z])

element_number_ID должно равняться '1' для извлечения нужной модели

    model_1_result <- allModelsResults$'1'

    ResultsTestPred <- predict(model_1_result, testing_data)
    results_to_store <- confusionMatrix(ResultsTestPred, testing_data $outcome)

aggregate_results  <- rbind(aggregate_results, results_to_store)

}

results_to_store вывод для одного элемента выглядит так:

Матрица путаницы и статистика

      Reference

Прогноз 0 1 0 14 2 1 4 19

           Accuracy : 0.8462          
             95% CI : (0.6947, 0.9414)
No Information Rate : 0.5385          
P-Value [Acc > NIR] : 0.00005274      

              Kappa : 0.688           

P-значение теста Макнемара: 0,6831

        Sensitivity : 0.7778          
        Specificity : 0.9048          
     Pos Pred Value : 0.8750          
     Neg Pred Value : 0.8261          
         Prevalence : 0.4615          
     Detection Rate : 0.3590          

Распространенность обнаружения: 0,4103
Сбалансированная точность: 0,8413

   'Positive' Class : 0       

Где я хочу сохранить Accuracy значение для каждого элемента / модели. Таким образом, я могу сравнить каждую спецификацию модели с точки зрения точности.

Любое понимание будет с благодарностью!

1 Ответ

0 голосов
/ 11 ноября 2018

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

Сначала получите прогнозы по данным тестирования. Все эти методы абсолютно одинаковы:

# lapply way
predictions = lapply(allModelsList, predict, newdata = testingdata)

# for loop way
predictions = list()
for (i in 1:length(allModelsList)) {
  predictions[[i]] = predict(allModelsList[[i]], newdata = testingdata)
}

# manual way - just so you understand exactly what's going on
predictions = list(
  predict(allModelsList[[1]], newdata = testingdata),
  predict(allModelsList[[2]], newdata = testingdata),
  predict(allModelsList[[3]], newdata = testingdata),
  ...
)

Теперь predictions - это list, поэтому мы получаем доступ к каждому элементу с помощью [[. Первый - predictions[[1]], k-й - predictions[[k]], если мы хотим определить некоторую переменную k (как в цикле). Мы могли бы также добавить описательные имена и использовать имена вместо индексов.

Аналогично, мы можем вычислить все матрицы путаницы:

# lapply way
conf_matrices = lapply(predictions, confusionMatrix, reference = testingdata$outcome)

# for loop way
conf_matrices = list()
for (p in 1:length(predictions)) {
  conf_matrices[[p]] = confusionMatrix(p, reference = testingdata$outcome)
}

# manual way (for illustration)
conf_matrices = list(
  confusionMatrix(predictions[[1]], reference = testingdata$outcome),
  confusionMatrix(predictions[[2]], reference = testingdata$outcome),
  ...
) 

Опять же, у нас есть list. Первая запутанная матрица conf_matrices[[1]] и все то же самое, что и выше.

Надеюсь, это поможет нам понять, как использовать цикл lapply или for для создания списка.


Теперь, ближе к сути вашего вопроса, вы, кажется, подразумеваете, что Accuracy часть матрицы путаницы. Я запустил пример внизу страницы справки ?confusionMatrix и посмотрел на результат. Запуск str(conf_mat) для результата показал мне, что это list, и что элемент "overall" списка является именованным вектором, включая "Accuracy". Таким образом, для отдельной матрицы путаницы cm мы можем извлечь точность с cm[["overall"]]["Accuracy"]. Мы используем [[ для list части и [ для регулярной векторной части. (Мы могли бы также использовать cm$overall["Accuracy"]. $, когда мы даем ему точное имя, без кавычек, без переменных. Кажется, что многие из ваших проблем связаны с попыткой использовать $ с кавычками или переменными. Вы просто не могу этого сделать. См. fortunes::fortune(312)).

Итак, мы можем извлечь точность из нашего списка матриц путаницы:

# I use *s*apply here so the result will be *s*implified into a vector
acc = sapply(conf_matrices, function(cm) cm[["overall"]]["Accuracy"])

acc = numeric(length(conf_matrices))
for (i in 1:length(conf_matrices)) {
  acc[i] = conf_matrices[[i]][["overall"]]["Accuracy"]
}

Или, если вы знаете с самого начала, что вам нужна только точность, мы можем попасть туда напрямую, не сохраняя промежуточные шаги:

# apply
acc = sapply(allModelsList, function(x) {
    pred = predict(x, newdata = testingdata)
    cm = confusionMatrix(pred, reference = testingdata$outcome
    return(cm[["overall"]]["Accuracy"]
  }
)

# для цикла acc = numeric (length (allModelsList)) для (я в 1: длина (allModelsList)) { pred = Forecast (allModelsList [[i]], newdata = testingdata) cm = confusionMatrix (pred, reference = testingdata $ output acc [i] = (см [["общий"]] ["Точность"] }


Примечания: Как уже упоминалось выше, без воспроизводимого примера, я предполагаю, что немного, и ничего из этого не проверено, потому что у меня нет входов для тестирования на . Я предполагаю, что то, что я вижу в вашем вопросе с точки зрения отдельных шагов, таких как то, что мы хотим предсказать для каждого элемента allModelResults, является правильным. (Если это так, кажется, скажем, fittedModels было бы гораздо лучшим именем, чем allModelResults.) Я не знаю, что вы подразумеваете под "спецификациями моделей", и я понятия не имею, что в allModelList, но, надеюсь, это даст вам достаточно примеров работы со списками, чтобы вы могли решить любые проблемы. (Также могут быть, скажем, несоответствующие скобки или пропущенные скобки.)

lapply и sapply удобны тем, что позволяют печатать меньше, чем цикл for, но на самом деле они ничем не отличаются. Они создали объект для хранения результатов и заполнили его. Если вы хотите создать несколько результатов одновременно, вы можете просто использовать цикл for. И поскольку количество шагов внутри становится длиннее, отладка цикла for в любом случае может быть проще. Используйте то, что вам нравится и что имеет для вас смысл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...