ohnoplus
ohnoplus

Reputation: 1325

purrr with linear model in R: invalid 'envir' argument of type 'character'

I have a data frame of species with different abundances and I want to see if their abundances are related to some parameter.

I think I ought to be able to do something like

# Load in the dune data set and tidyverse
library(vegan)
data(dune)
data(dune.env)
library(tidyverse)

# Reshape the species matrix into long form data
duneM <- dune %>% rownames_to_column('Site') %>% gather(Species, Count, -Site)

# Join the species and environmental data
duneE <- dune.env %>% rownames_to_column('Site')
duneJ <- left_join(duneM, duneE, by = 'Site')

# Basic linear model, that compares species counts to moisture data
my_lm <- function(df){
    lm(Count ~ Moisture, data = df)
}

# Group the data by species and apply the function to each one
duneJ %>% group_by('Species') %>% map(my_lm)

To my surprise, I am getting the following error message.

Error in eval(predvars, data, env): invalid 'envir' argument of type 'character' Traceback:

  1. duneJ %>% group_by("Species") %>% map(my_lm)
  2. withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
  3. eval(quote(`_fseq`(`_lhs`)), env, env)
  4. eval(quote(`_fseq`(`_lhs`)), env, env)
  5. `_fseq`(`_lhs`)
  6. freduce(value, `_function_list`)
  7. withVisible(function_list[k])
  8. function_list[k]
  9. map(., my_lm)
  10. .f(.x[[i]], ...)
  11. lm(Count ~ Moisture, data = df) # at line 2 of file
  12. eval(mf, parent.frame())
  13. eval(mf, parent.frame())
  14. stats::model.frame(formula = Count ~ Moisture, data = df, drop.unused.levels = TRUE)
  15. model.frame.default(formula = Count ~ Moisture, data = df, drop.unused.levels = TRUE)
  16. eval(predvars, data, env)

Clearly, I am missing something here. Could somebody please clarify? Thanks.

Upvotes: 0

Views: 3925

Answers (1)

ohnoplus
ohnoplus

Reputation: 1325

It helped me to look at this post http://omaymas.github.io/Climate_Change_ExpAnalysis/, and this video https://www.youtube.com/watch?v=rz3_FDVt9eg to understand how to best use purrr and broom together. As G. Grothendeik points out, I can add a column with models to a data frame (where each cell is a full model). The way to do this with the map function is

 duneJ %>% group_by(Species) %>% nest %>% mutate(Mod = map(data, my_lm0)) -> test

Here, nest is a key function that makes a column that is a list of data frames, each of which contain the data about each species and saves it to a default column named "data". I run map inside of the mutate funciton to save the models to yet another column, where each cell is a new model.

If I want to look at model results, I can combine them into a list of data frames with map and broom, select the relevant data, and then unnest them, like so:

 test %>% mutate(Glance = map(Mod, glance)) %>% select(Species, Glance) %>% unnest

This gets me a new data frame that has model results for each species, which was what I was ultimately aiming for, even if I didn't fully explain that in the question.

Upvotes: 0

Related Questions