добавление операторов if в функцию, возвращающую ошибку - PullRequest
0 голосов
/ 11 февраля 2020

Это продолжение поста, который я выложил ранее. Код следующий:

data(iris)
df <- iris %>% 
  filter(Species != "setosa") %>% 
  mutate(Species = +(Species == "virginica")) %>% 
  sample_n(10)

##########################################
var_combos <- expand.grid(colnames(df[,1:4]), colnames(df[,1:4])) %>% 
  filter(!Var1 == Var2)

boundary_lists <- map2(
  .x = var_combos$Var1,
  .y = var_combos$Var2,
  ~select(df, .x, .y) %>% 
    summarise(
      minX = min(.[[1]], na.rm = TRUE),
      maxX = max(.[[1]], na.rm = TRUE),
      minY = min(.[[2]], na.rm = TRUE),
      maxY = max(.[[2]], na.rm = TRUE)
      )
  ) %>% 
  map(.,
      ~tibble(
        x = seq(.x$minX, .x$maxX, length.out = 200),
        y = seq(.x$minY, .x$maxY, length.out = 200),
        )
      ) %>% 
  map(.,
      ~tibble(
        xx = rep(.x$x, each = 200),
        yy = rep(.x$y, time = 200)
        )
      ) %>% 
  map2(.,
       asplit(var_combos, 1), ~ .x %>% 
         set_names(.y))


# xgboost(
#   objective='binary:logistic',
#   eval_metric = 'auc',
#   data = as.matrix(df[, 1:2]),
#   label = as.matrix(df[, 5]), # binary variable
#   nrounds = 10
#   )

models_list <- map2(
  var_combos$Var1,
  var_combos$Var2,
  ~df %>%
    select(Species, .x, .y) %>%
    group_by(grp = 'grp') %>% 
    nest() %>%
    mutate(
      models = map(
        data, 
        ~{
          list(
            glm(Species ~ ., data = .x, family = binomial(link='logit')),
            e1071::svm(Species ~ ., data = .x,  type = 'C-classification', kernel = 'linear'),
            randomForest::randomForest(formula = as.factor(Species) ~ ., data = .),
            xgboost(
              objective='binary:logistic',
              eval_metric = 'auc',
              data = as.matrix(.x[, 2:3]),
              label = as.matrix(.x$Species), # binary variable
              nrounds = 10
            )
          )
        }
      )
    )
) %>% 
  map(
    ., ~unlist(., recursive = FALSE)
  )

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

Я хотел бы создать новая функция predict и tibble для каждой модели, в которой я тренируюсь, где я могу изменить данные внутри каждого из операторов ~if. Код, который я имею:

    map2_dfr(models_list, boundary_lists, ~{
  mods <- pluck(.x, "models")
  dat <- .y
  map_dfr(mods,

          ~if(attr(.x, "class")[1] == "glm"){              # predict the logistic model
            tibble(
              modelname = attr(.x, "class")[1],
              prediction = predict(.x, newdata = dat)
              )
          }

          ~if(attr(.x, "class")[1] == "svm.formula"){      # predict the SVM model
            tibble(
              modelname = attr(.x, "class")[1],
              prediction = predict(.x, newdata = dat)
              )
          }

          ~if(attr(.x, "class")[1] == "randomForest.formula"){   # predict the RF model
            tibble(
              modelname = attr(.x, "class")[1],
              prediction = predict(.x, newdata = dat)
              )
          }

          ~if(attr(.x, "class")[1] == "xgb.Booster"){       # predict the XGBoost model
            tibble(
              modelname = attr(.x, "class")[1], 
              prediction = predict(.x, newdata = as.matrix(dat), type = 'prob')
              ) 
          }
      #else {
      #  tibble(modelname = attr(.x, "class")[1],
      #         prediction = predict(.x, newdata = dat))}   )   

  )
  }
  )

, который дает мне ошибку:

Error: unexpected ')' in "  )"
>   }
Error: unexpected '}' in "  }"
>   )
Error: unexpected ')' in "  )"

Кажется, я не могу найти, где находится неожиданная часть кода. Я "предполагаю", что есть проблема со мной, передавая операторы ~if. Как я могу передать несколько if операторов в этом mannor?

1 Ответ

1 голос
/ 11 февраля 2020

Вот метод, который работает:

library(tidyverse)

output <- map2_df(models_list, boundary_lists, ~{
    mods <- purrr::pluck(.x, "models")
    dat <- .y
    map_df(mods, function(x)
      tryCatch({
          if(attr(x, "class")[1] == "glm"){   
           # predict the logistic model
            tibble(
              modelname = attr(x, "class")[1],
              prediction = predict(x, newdata = dat)
             )
            }    
          else if(attr(x, "class")[1] == "svm.formula"){ 
               # predict the SVM model
            tibble(
              modelname = attr(x, "class")[1],
              prediction = as.numeric(as.character(predict(x, newdata = dat)))
             )
            }
          else if(attr(x, "class")[1] == "randomForest.formula"){  
               # predict the RF model
            tibble(
             modelname = attr(x, "class")[1],
             prediction = as.numeric(as.character(predict(x, newdata = dat)))
            )
          }    
          else if(attr(x, "class")[1] == "xgb.Booster"){      
               # predict the XGBoost model
            tibble(
             modelname = attr(x, "class")[1], 
             prediction = predict(x, newdata = as.matrix(dat), type = 'prob')
            ) 
          }
       }, error = function(e) { print('skipping\n')})
      )
 })

Я сделал следующие изменения:

  • Используется ~ только один раз в начале функции, а не для каждые if
  • Поскольку это вложенный map, использование .x может создать путаницу в отношении того, к чему он относится. Следовательно, во внутреннем блоке map_df используется анонимная функция, поэтому аргументы map2_df обозначаются .x и .y, а аргументы map_df - x.
  • Некоторые модели возвращаем прогнозируемую переменную как factors, следовательно, оборачиваем as.numeric(as.character()) вокруг них.
  • Добавлен tryCatch для лучшей обработки исключений.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...