CornellLabofOrnithology / ebird-best-practices

Best Practices for Using eBird Data
https://CornellLabOfOrnithology.github.io/ebird-best-practices/
Other
32 stars 12 forks source link

mutate argument not working for pland #5

Closed lime-n closed 4 years ago

lime-n commented 4 years ago

I have checked using the original dataset and the code uploaded does not work.

when I insert this code, I get:

lc_extract <- ebird_buff %>% 
  mutate(pland = map2(year_lc, data, calculate_pland, lc = landcover)) %>% 
  select(pland) %>% 
  unnest(cols = pland)

Error: Problem with mutate() input pland. x error in evaluating the argument 'x' in selecting a method for function 'exact_extract': invalid layer names i Input pland is map2(year_lc, data, calculate_pland, lc = landcover).

Which is strange, as I have all the packages loaded and all went fine previously, except for unpacking the MODIS data, which I then had to remove st_buffer(dist = 10000) from the code for it to download correctly, an explanation of this would also be great. I used a .gpkg from GADM of Australia.

an image of my current environment: image

mstrimas commented 4 years ago

Tough to see what's going on here, try calling the function directly and see what the error is: calculate_pland("y2010", ebird_buff$data[[1]], lc = landcover)

lime-n commented 4 years ago

Thanks for the reply!

when I enter the code you mention, I get this:

> calculate_pland("y2010", ebird_buff$data[[1]], lc = landcover)
# A tibble: 13,108 x 4
   year  locality_id landcover     n
   <chr> <chr>           <int> <int>
 1 2013  L928124             0     2
 2 2013  L928124            13    28
 3 2013  L1893517            9     2
 4 2013  L1893517           10     8
 5 2013  L1893517           11     1
 6 2013  L1893517           12    19
 7 2013  L1922157            9     3
 8 2013  L1922157           10     1
 9 2013  L1922157           12     1
10 2013  L1922157           13    26
# ... with 13,098 more rows

However, when I used the code to iterate over all checklists lc_extract it always returns the error as shown below. I double-checked by trying the same code with the data provided to see if it was my dataset at fault, and that also returned the same error.

I have added further information on the error:

> lc_extract <- ebird_buff %>% 
+     mutate(pland = map2(year_lc, data, calculate_pland, lc = landcover)) %>% 
+     select(pland) %>% 
+     unnest(cols = pland)
 Error: Problem with `mutate()` input `pland`.
x error in evaluating the argument 'x' in selecting a method for function 'exact_extract': invalid layer names
i Input `pland` is `map2(year_lc, data, calculate_pland, lc = landcover)`.

Run `rlang::last_error()` to see where the error occurred. 

> rlang::last_error()
<error/dplyr_error>
Problem with `mutate()` input `pland`.
x error in evaluating the argument 'x' in selecting a method for function 'exact_extract': invalid layer names
i Input `pland` is `map2(year_lc, data, calculate_pland, lc = landcover)`.
Backtrace:
 2. dplyr::mutate(...)

Run `rlang::last_trace()` to see the full context.

> rlang::last_trace()
<error/dplyr_error>
Problem with `mutate()` input `pland`.
x error in evaluating the argument 'x' in selecting a method for function 'exact_extract': invalid layer names
i Input `pland` is `map2(year_lc, data, calculate_pland, lc = landcover)`.
Backtrace:
     x
  1. +-`%>%`(...)
  2. | +-base::withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
  3. | \-base::eval(quote(`_fseq`(`_lhs`)), env, env)
  4. |   \-base::eval(quote(`_fseq`(`_lhs`)), env, env)
  5. |     \-`_fseq`(`_lhs`)
  6. |       \-magrittr::freduce(value, `_function_list`)
  7. |         \-function_list[[i]](value)
  8. |           +-dplyr::mutate(...)
  9. |           \-dplyr:::mutate.data.frame(...)
 10. |             \-dplyr:::mutate_cols(.data, ...)
 11. |               +-base::withCallingHandlers(...)
 12. |               \-mask$eval_all_mutate(dots[[i]])
 13. +-purrr::map2(year_lc, data, calculate_pland, lc = landcover)
 14. | \-global::.f(.x[[i]], .y[[i]], ...)
 15. |   +-`%>%`(...)
 16. |   | \-base::eval(lhs, parent, parent)
 17. |   |   \-base::eval(lhs, parent, parent)
 18. |   +-exactextractr::exact_extract(lc[[yr]], regions, progress = FALSE)
 19. |   +-lc[[yr]]
 20. |   \-lc[[yr]]
 21. |     \-raster:::.local(x, i, j, ...)
 22. |       +-base::subset(x, i, drop = drop)
 23. |       \-raster::subset(x, i, drop = drop)
 24. |         \-raster:::.local(x, ...)
 25. |           \-base::stop("invalid layer names")
 26. +-base::.handleSimpleError(...)
 27. | \-base:::h(simpleError(msg, call))
 28. \-base::.handleSimpleError(...)
<error/simpleError>
error in evaluating the argument 'x' in selecting a method for function 'exact_extract': invalid layer names
mstrimas commented 4 years ago

Can you give me the output of head(ebird_buff) and names(landcover)?

lime-n commented 4 years ago

Certainly!

head(ebird_buff)
# A tibble: 6 x 2
  year_lc data                 
  <chr>   <list>               
1 y2013   <tibble [4,502 x 3]> 
2 y2015   <tibble [16,583 x 3]>
3 y2019   <tibble [39,491 x 3]>
4 y2017   <tibble [25,392 x 3]>
5 y2007   <tibble [931 x 3]>   
6 y2006   <tibble [919 x 3]>   

 names(landcover)
 [1] "y2001" "y2002" "y2003" "y2004" "y2005" "y2006" "y2007" "y2008" "y2009" "y2010" "y2011" "y2012" "y2013"
[14] "y2014" "y2015" "y2016" "y2017" "y2018" "y2019"
mstrimas commented 4 years ago

It's tough for me to debug this because I can't reproduce your issue, everything works fine for me. Either you must have changed something when you ran on the original dataset or you may have an outdated package version. I think the way I've written it in the book makes it hard to understand what's going on and to debug, so try this instead. It does the same thing, but should be easier to understand and hopefully helps you find the error:

lc_extract <- NULL
for (yr in names(landcover)) {
  # get the buffered checklists for a given year
  regions <- ebird_buff$data[[which(yr == ebird_buff$year_lc)]]
  # get landcover values within each buffered checklist area
  ee <- exact_extract(landcover[[yr]], regions, progress = FALSE)
  # count the number of each landcover class for each checklist buffer
  ee_count <- map(ee, ~ count(., landcover = value))
  # attach the year and locality id back to the checklists
  ee_summ <- tibble(st_drop_geometry(regions), data = ee_count) %>% 
    unnest(data)
  # bind to results
  lc_extract <- bind_rows(lc_extract, ee_summ)
}
lime-n commented 4 years ago

The code works perfectly, thank you!

mstrimas commented 4 years ago

Great, glad it's working!