How to tidy() on map() model results

If I run tidy() on my map() results:

map(.x = levels(Orange$Tree), .f = function(z){lm(formula = age ~ 1 + circumference, subset = Tree == z, data = Orange)}) %>% 
  tidy()

I get an error:
"Error in names(object) <- nm :
'names' attribute [1] must be the same length as the vector [0]
In addition: Warning message:
In is.na(x) : is.na() applied to non-(list or vector) of type 'NULL'"

Which confirms that I don't know what I'm doing. :slight_smile:

Does anyone have a suggestion?

Would you be able to make this into a minimal reproducible example (aka a reprex)?

In addition to the reprex section of the tidyverse site (linked to above), there's a quick, helpful overview of the package and how to use it (Jenny starts ~10:40) in the video below.

You can also see the slides from that video here:

The problem you're encountering (I think) is that map() returns a list of lm objects (one for each level of Tree as per your call). And tidy() doesn't know how to operate on a list of lm objects, just on a single lm object.

So you need to iterate over your list, tidy()ing each element. Luckily you already know how to do that (with map())! I got the the following code to work (indentation/formatting not really that important):

map(
    .x = levels(Orange$Tree), 
    .f = function(z) {
        lm(formula = age ~ 1 + circumference, subset = Tree == z, data = Orange)
        }
    ) %>% 
  map(tidy)
2 Likes

Thanks Jim! You nailed it.

You could also do it like this:

Orange %>%
  group_by(Tree) %>%
  nest() %>%
  mutate(model = map(data, ~ lm(age ~ 1 + circumference, data = .x)),
        tidy_model = map(model, broom::tidy)) %>%
  unnest(tidy_model)

This will give you a data frame with all of the different models in the same data frame rather than in a list of data frames.

More similar to your accepted answer, you could change the map(tidy) portion to map_df(tidy) and you would get the same thing. The nice thing about the first approach is that you can do a lot more than just tidy the models, i.e., augment or glance, all in the same mutate call and then just unnest which ever you are interested in.

5 Likes

You'll need to drop the parentheses on broom::tidy() to get this to run, but in the long big picture this is a much more useful idiom.

2 Likes

Oops, you are correct! I have corrected my response. I overlooked that since I was typing directly into the browser