Map2() - Specify predict type


#1

Good day.

I’ve been scouring the web for the last few days looking at the documentation for map2. I have taken a training set, nested the data and created coxph models for it, saving those models in the nested table. Now I want to predict from that model, but I want to use a type=“expected”. I’m not seeing how to get that to work. I’m still pretty new to R; learned a lot from the RStudio conference and tidyverse workshop, so really looking to continue my learning in tidy-land.

I’ve adapted the relevant code to reproduce my issues using the mpg data set.

I have 4 examples below that do not work after the predict function that does work.

Thanks in advance for the help!

#Needed libraries
library(reprex)
library(ggplot2)
library(tidyverse)
library(purrr)
library(broom)
library(survival)

#Create data set
mpg_data <- mpg
mpg_data <- mpg_data %>% 
  mutate(mpg_diff = cty - hwy)

mpg_data <- mpg_data %>% 
  mutate(EVENT = (mpg_diff >= -8))

set.seed(1)
mpg_data <- mpg_data %>% 
  mutate(TIME_TO_EVENT = as.integer(runif(234, 1, 100)))

mpg_nested <- mpg_data %>% 
  group_by(manufacturer) %>% 
  mutate(n_prot = length(model)) %>% 
  nest()

# Stepwise regression 
stepwise <- function(data) {
  response <- Surv(time = data$TIME_TO_EVENT, event = data$EVENT, type = "right") 
  
  full <- "Surv(time = data$TIME_TO_EVENT, event = data$EVENT, type = 'right') ~ data$cyl+data$cty+data$hwy+data$displ"
  x <- factor(as.factor(data$model))
  full <- ifelse(nlevels(x) >= 2, paste(full, "as.character(data$model)", sep = "+"), full)
  x <- factor(as.factor(data$trans))
  full <- ifelse(nlevels(x) >= 2, paste(full, "as.character(data$trans)", sep = "+"), full)
  x <- factor(as.factor(data$drv))
  full <- ifelse(nlevels(x) >= 2, paste(full, "as.character(data$drv)", sep = "+"), full)
  
  null_model_ONE <- coxph(response ~ 1, data=data)
  
  full_model_ONE <- coxph(as.formula(full), data=data) 
  
  model_ONE <- step(null_model_ONE, scope=list(lower=null_model_ONE, upper=full_model_ONE))
}

survival_mpg <- mpg_nested %>%  
  mutate(model_fit = map(data, stepwise))

#Predicting values
#This works but is not type="expected"
survival_mpg_predict <- survival_mpg %>% 
  mutate(mpg_predict = map2(model_fit, data, predict))

##TRY 1##
predict.F <- function(model_fit, data){
  predict(model_fit, newdata=data, type="expected")
}

survival_mpg_predict <- survival_mpg %>% 
  mutate(mpg_predict = map2(model_fit, data, predict.F))
#Error in mutate_impl(.data, dots) : Evaluation error: requires numeric/complex matrix/vector arguments.

##Try 2##
survival_mpg_predict <- survival_mpg %>% 
  mutate(mpg_predict = map2(model_fit, data, predict(model_fit, newdata = data, type="expected")))
#Error in mutate_impl(.data, dots) : Evaluation error: no applicable method for 'predict' applied to an object of class "list".

##Try 3##
survival_mpg_predict <- survival_mpg %>% 
  mutate(mpg_predict = map2(model_fit, data, ~ predict(.x, newdata = .y, type="expected")))
#Error in mutate_impl(.data, dots) : Evaluation error: requires numeric/complex matrix/vector arguments.

##Try 4##
survival_mpg_predict <- survival_mpg %>% 
  mutate(mpg_predict = map2(model_fit, data, function(model_fit, data) predict(model_fit, newdata=data, type="expected")))
#Error in mutate_impl(.data, dots) : Evaluation error: requires numeric/complex matrix/vector arguments.

#2

So I don’t have a definite solution for you but I can tell you that your issue is not with your map2 call. Try 1, 3, and 4 are all valid ways of passing your predict function into map functions (although 3 might be the best option in this case, and my personal favorite).

The error you are getting seems to be with the the predict function itself, specifically when you use type = 'expected'. I have never worked with this type of model so I am not familiar with its methods off hand but hopefully this will help you look in the right places for the solution.

This is just a guess, but it may have something to do with some of the models being of class coxph.null


#4

So, I filtered out the models that have a class of coxph.null and I still get the same errors from those different functions.


#5

I also tried:

survival_mpg_pred_exp = survival_mpg %>%
  mutate(mpg_predict = map2(model_fit, data, predict, type = 'expected'))

Since you can directly pass arguments to .f via most map functions (ie. map2(.x, .y, .f, ...) where ... is the arguments passed on). But it produces the same error as the anonymous function method you used in Try #3:

Error in mutate_impl(.data, dots) :
Evaluation error: requires numeric/complex matrix/vector arguments.

So I agree that the problem is with your function. But I’m not familiar enough with how predict.coxph works to be much help, sorry :confused:


#6

I was able to get some help from Stack Overflow. Here is the answer for this community:

Modifying ##TRY 1## to remove the newdata argument and change the map2() function to the map() function worked

predict.F <- function(model_fit, data){
predict(model_fit, type="expected")
}
survival_mpg_predict <- survival_mpg %>% 
mutate(mpg_predict = map(model_fit, predict.F))