Доступ к подэлементу всех элементов списка - PullRequest
0 голосов
/ 10 апреля 2019

Я пытаюсь безопасно использовать () из пакета purrr вместе с регрессией лассо из пакета glmnet. Я застрял в части перекрестной проверки, поскольку safe () возвращает список с двумя элементами: $ results и $ errors. Я пытаюсь получить только $ результаты с помощью dplyr, но не могу заставить его работать.

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

library(dplyr)
library(glmnet)
library(purrr)
data(iris)

# Group to perform regressions for every species
grouped <- iris %>% 
  group_by(Species)

# Make model matrices
mm <- grouped %>%
  do(mm = safely(model.matrix)(Sepal.Length ~ Sepal.Width + Petal.Width, data = .)[1])

# Join the dependent values with the model matrices in a tibble
sepallengths <- grouped %>% 
  summarise(Sepal.Length = list(Sepal.Length))
temp <- inner_join(sepallengths, mm, by = "Species")

# Perform cross validation using the tibble above
cv_holder <- temp %>% 
  group_by(Species) %>% 
  # How to get this to work inside dplyr?
  do(cv = safely(cv.glmnet)(.$mm[1]$result, .$Sepal.Length, alpha = 1, nlambda = 100))

# Contains only errors when it should contain the cross validations
cv_holder$cv

# Works for individual lists this way
safely(cv.glmnet)(temp$mm[[1]][1]$result, temp$Sepal.Length[[1]], alpha = 1, nlambda = 100)$result

Я ожидаю, что результатом будет столбец (cv_holder) со столбцом (cv), который содержит списки, содержащие списки перекрестных проверок для каждого вида. Однако я могу заставить dplyr возвращать только ошибки, такие как «simpleError в rep (1, N): неверный аргумент« times »»

Вот как это можно сделать с помощью цикла:

for(i in 1:length(temp$mm)){
    print(safely(cv.glmnet)(temp$mm[[i]][1]$result, temp$Sepal.Length[[i]], alpha = 1, nlambda = 100))
cv_holder$error <- NULL
}

Ответы [ 2 ]

0 голосов
/ 11 апреля 2019

Я получил его для работы с plur'ом мурлыкания (), который выбирает первый элемент из каждого списка:

cv_holder <- temp %>% 
    group_by(Species) %>% 
    # Using pluck()
    do(cv = safely(cv.glmnet)(pluck(.$mm, 1)$result, pluck(.$Sepal.Length, 1), alpha = 1, nlambda = 100))

# Now works as intended
cv_holder$cv
0 голосов
/ 10 апреля 2019

Вам по-прежнему нужно индексировать в списке, даже если есть только 1 значение.

например:.

cv_holder <- temp %>% 
  group_by(Species) %>% 
  # How to get this to work inside dplyr?
  do(cv = safely(cv.glmnet)(.$mm[1][[1]]$result, .$Sepal.Length[[1]], alpha = 1, nlambda = 100))

Это просто мнение, но: используйте tidyverse, когда данные аккуратны. Используйте цикл for, когда это оправдано. Я не вижу смысла пытаться втиснуть что-то в структуру dplyr, когда это, очевидно, просто более запутанно.

...