0
votes

New to purrr question: I am trying to vectorize my code by applying a function across groups in R using the map() package, and I just can't seem to get it right. Here's my example, working across copy-paste, for loop, and then map examples.

species <- rep(seq(1:3), times = 10)
bio_data <- bind_cols(length = rnorm(n = 30, mean = 50, sd = 25), 
                      weight = rnorm(n = 30, mean = 100, sd = 35))

dat <- bind_cols(species = species, bio_data)

# test --------------------------------------------------------------------

# manually get mean by species:
dat %>% filter(species == 1) %>% summarize(mean_wt = mean(weight))
dat %>% filter(species == 2) %>% summarize(mean_wt = mean(weight))
dat %>% filter(species == 3) %>% summarize(mean_wt = mean(weight))

# create function and loop over function:
get_mean <- function(data, group){
  data %>% 
    dplyr::filter(species == group) %>% 
    summarise(mean_wt = mean(weight))
}

for(i in unique(species)){
  print(get_mean(dat, i))
}

# use purrr map() package
results <- map(dat, get_mean, group = unique(species))

This last line using map() with the get_mean() function above returns an error with the use of 'filter' and I'm not sure why?

Error in UseMethod("filter_") : 
no applicable method for 'filter_' applied to an object of class "c('integer', 'numeric')" 

How can I get my code to produce the mean weights for each species?

1

1 Answers

1
votes

The looping should be on unique(species)

library(purrr)
# // without the lambda call
map(unique(dat$species), get_mean, data = dat)
# // with lambda call
map(unique(dat$species), ~ get_mean(dat, .x))

-output

#[[1]]
# A tibble: 1 x 1
#  mean_wt
#     <dbl>
#1    88.2

#[[2]]
# A tibble: 1 x 1
#  mean_wt
#    <dbl>
#1    105.

#[[3]]
# A tibble: 1 x 1
#  mean_wt
#    <dbl>
#1    124.

Generally, this would be a group_by operation

dat %>%
   group_by(species) %>%
   summarise(mean_wt = mean(weight), .groups = 'drop')

-output

# A tibble: 3 x 2
#  species mean_wt
#*   <int>   <dbl>
#1       1    88.2
#2       2   105. 
#3       3   124.