TITLE: Using `any()` with `ifelse()` and `group_by()` DATE: 2022-08-14 AUTHOR: John L. Godlee ==================================================================== I am doing some more work to update the SEOSAW database. When we measure the growth and mortality of trees to monitor biomass dynamics, it is important to have a consistent way of recording mortality. For trees, especially trees with multiple stems, the concept of "death" is not as simple as for animals. We generally classify a tree as dead if all the above-ground tissue on the tree appears to be dead, i.e. has no living leaves or buds, and no sap below the bark. Sometimes though, a single stem on a multi-stemmed tree will die, but the rest of the tree continues to live. Sometimes a stem or tree may appear dead, but comes back to life later. In savanna systems especially, it's fairly common for trees to partially die, or to resurrect after a disturbance event like a drought or a fire. [SEOSAW database]: https://seosaw.github.io In SEOSAW we previously classified stems as either "alive", "topkilled", "resprouting" or "dead". I first heard the term topkill used in a paper by Bill Hoffmann (Hoffmann et al. 2009), where they define it as "the complete death of aerial biomass". In SEOSAW we tried to tighten up the term a bit by defining it as a stem where there is no living tissue above the point of DBH measurement. A resprouting stem is defined as a topkilled stem where there is new material sprouting from the stem. The difficulty with this old system was that it was very subjective to decide whether a stem was topkilled or dead, and whether a stem was resprouting or top-killed. How do you define whether living tissue on a stem is the result of resprouting? Does resprouting tissue have to be growing directly from the above-ground parts of the topkilled stem to be classed as resprouting? [Hoffmann et al. 2009]: https://doi.org/10.1890/08-0741.1 We recently came up with a revised mortality classification. This classification only has "alive", "resprouting", and "dead". A stem is classified as resprouting if it doesn't appear to have any living tissue above the DBH measurement, but there are signs of life elsewhere on the tree. Other signs of life can come from other stems on the tree, from resprouting material at the base of the tree, or from resprouting material on the stem of interest below the DBH measurement. A stem can only be classified as dead if all stems on the tree are dead and there is no sign of life anywhere else on the above-ground parts of the organism. It follows then that on a multi-stemmed tree, a stem cannot be classified as dead unless all other stems on the tree are dead. Additionally however, even if all stems on a tree are lacking living tissue this still doesn't mean that the stems will be classified as dead if there is living material somewhere else on the tree, i.e. from the base of the stool on a heavily coppiced individual. In light of this new classification, I had to adjust the mortality data in some old censuses. I wrote a check that would flag stems classified as dead when other stems on the tree were classified as alive or resprouting. # Split data by plot ID, tree ID, and census date x_split <- split(x, list(x$plot_id, x$tree_id, x$census_date), drop = TRUE) # Only check trees with more than one stem x_split_fil <- x_split[unlist(lapply(x_split, nrow)) > 1] # If there are some trees with multiple stems, check each one if (length(x_split_fil) > 0) { # For each tree x_zomb <- unlist(lapply(x_split_fil, function(i) { # Flag if any stems are dead and any other stems are alive or resprouting status <- i$stem_status[!is.na(i$stem_status)] any(status == "d") & any(status %in% c("a", "r")) })) names(x_zomb[x_zomb]) } I also concocted a little snippet using {dplyr} that I could use to adjust the values of stems that had been classified as dead to resprouting. x %>% group_by(plot_id, tree_id, census_date) %>% mutate( stem_status = case_when( # If any stems on the tree are alive or resprouting # change dead stems to resprouting any(stem_status %in% c("a", "r")) & stem_status == "d" ~ "r", TRUE ~ stem_status) )