Manhattan’s Urban Forestry Report, 2015

Manhattan’s Urban Forestry Report, 2015

0. Executive Summary

Based on the data and results, the tree population and species present in Manhattan, NYC, can be summarized as follows:

  • Greater numbers of trees are most likely to be found in neighborhoods with larger plots of land.
  • The majority of the trees in Manhattan are on-curb, with only a few that are offset from the curb.
  • The majority of the trees in Manhattan are alive and in fair to good health, while only a small number are dead and in poor health.
  • Although specific root, trunk, and branch problems are not of significant concerns, few of the trees are affected by paving stones in the tree bed (a kind of root problem) as well as other unspecified trunk and branch problems.
  • Manhattan has a rich and diverse set of tree species.
  • The species recommendation for tree planting in Manhattan’s streets is a combination of some of the borough’s highly and averagely abundant species that have shown favorable qualities of size and health. Specifically, the following are the five species that are highly recommended:

    1. Siberian elm
    2. Willow oak
    3. Honeylocust
    4. American elm
    5. Pin oak

1. Background

1.1. Introduction

The urban design team believes that tree size (in terms of trunk diameter) and health are the most desirable characteristics of city trees. In order to help the planning department improve the quantity and quality of trees in New York City, our organization is advised to provide a data analysis report.

1.2. Objectives

The main objective of this report is to profile Manhattan’s tree population and species by different attributes using summary statistics, visualizations, and textual explanations. Specifically, it aims to:

  1. Describe all censused trees by their spatial and biological characteristics.
  2. Map the tree profile of the neighborhoods.
  3. Illustrate the biodiversity and biology of the tree species in Manhattan.
  4. Determine tree species with the best traits.

1.3. Libraries

# Load required packages
library(tidyverse)
library(dplyr)
library(ggplot2)
library(sf)
library(geojsonsf)
library(geojsonio)
library(scales)
library(remotes)
library(rwantshue)
library(ggfun)
library(ggchicklet)

1.4. Datasets

The datasets presented below are sourced from the NYC Open Data provided by the City of New York.

# Read the 'trees' data set from the CSV file
trees <- read_csv("data/trees.csv", show_col_types=FALSE) %>%
  mutate(spc_common = str_to_sentence(spc_common))

# Read the 'neighborhoods' data set from the SHP file
neighborhoods <- st_read("data/nta.shp", quiet=TRUE) %>% 
  select(boroname, ntacode, ntaname, geometry, shape_area)

# Create a merged data frame for the 'trees' and 'neighborhoods' data sets
merged_trees_and_neighborhoods <- trees %>%
  full_join(neighborhoods, by = c("nta"="ntacode", "nta_name"="ntaname"))

# Total number of censused trees (Population)
N_trees <- trees %>%
  summarize(total_number_of_censused_trees = n())

1.4.1. Trees

Based on the TreesCount! 2015 Street Tree Census, this dataset was collected by volunteers and staff organized by NYC Parks & Recreation, along with partner organizations. It includes information on tree species, diameter, and perceived health. Accompanying blockface data indicate the status of data collection and release across the city.

VariableDescription
tree_idUnique id of each tree
tree_dbhThe diameter of the tree in inches measured at 54 inches above the ground
curb_locLocation of the tree bed in relation to the curb Either along the curb (OnCurb) or offset from the curb (OffsetFromCurb)
spc_commonCommon name for the species
statusIndicates whether the tree is alive or standing dead
healthIndication of the tree’s health (Good, Fair, and Poor)
root_stoneIndicates the presence of a root problem caused by paving stones in the tree bed
root_grateIndicates the presence of a root problem caused by metal grates in the tree bed
root_otherIndicates the presence of other root problems
trunk_wireIndicates the presence of a trunk problem caused by wires or rope wrapped around the trunk
trnk_lightIndicates the presence of a trunk problem caused by lighting installed on the tree
trnk_otherIndicates the presence of other trunk problems
brch_lightIndicates the presence of a branch problem caused by lights or wires in the branches
brch_shoeIndicates the presence of a branch problem caused by shoes in the branches
brch_otherIndicates the presence of other branch problems
postcodeFive-digit zip code where the tree is located
ntaNeighborhood Tabulation Area (NTA) code from the 2010 US Census for the tree
nta_nameNeighborhood name
latitudeLatitude of the tree in decimal degrees
longitudeLongitude of the tree in decimal degrees

1.4.2. Neighborhoods

This dataset is based on the boundaries of Neighborhood Tabulation Areas (NTAs), created by the NYC Department of City Planning using whole census tracts from the 2010 Census as building blocks. These aggregations of census tracts form subsets of New York City’s 55 Public Use Microdata Areas (PUMAs).

VariableDescription
ntacodeNTA code
ntanameNeighborhood name
geometryPolygon that defines the neighborhood

2. Results & Discussion

2.1. Tree Population

Using descriptive and spatial analyses, the following information outlines the location and physical attributes of all Manhattan trees in 2015 with a population size (\(N\)) of 64,229:

2.1.1. Spatial

2.1.1.1. Tree Location by Neighborhood
# Top 10 NTAs in terms of shape size 
top_nta_area <- neighborhoods %>%
  filter(boroname == "Manhattan", ntacode != "MN99") %>%
  arrange(desc(shape_area)) %>%
  slice(1:10)

# Tree count per neighborhood
nbh_tree_cnts <- merged_trees_and_neighborhoods %>%
  filter(boroname == "Manhattan", nta != "MN99") %>%
  group_by(nta, nta_name) %>%
  summarize(number_of_trees = n(), .groups="keep") %>%
  arrange(desc(number_of_trees)) %>%
  ungroup() %>%
  mutate(proportion = round(number_of_trees/sum(number_of_trees), digits = 4))

# Species richness per neighborhood
nbh_rchns <- trees %>%
  filter(!(spc_common=="null")) %>%
  group_by(nta, nta_name) %>%
  summarize(richness = n_distinct(spc_common), .groups="keep") %>%
  arrange(desc(richness)) %>%
  ungroup()

# Data for maps
nbhs_map <- nbh_tree_cnts %>%
  full_join(neighborhoods, c("nta"="ntacode", "nta_name"="ntaname")) %>% 
  full_join(nbh_rchns, c("nta", "nta_name")) %>%
  mutate(borough = substr(nta, 1, 2),
         nta_code_and_name = paste(nta, nta_name, sep=": "),
         nta_and_tree_cnt = ifelse(number_of_trees < 1000, 
                                   paste(nta,  " - ", "   ", prettyNum(number_of_trees,big.mark=","), " : ", nta_name, sep=""),
                                   paste(nta,  " - ", prettyNum(number_of_trees, big.mark=","), " : ", nta_name, sep="")
         ),
         nta_and_rchns = paste(nta,  " - ", prettyNum(richness, big.mark=","),
                               " : ", nta_name, sep="")
  ) %>%
  st_as_sf %>%
  st_transform("+proj=longlat +ellps=intl +no_defs +type=crs") 

# Colorize the NTAs
color_scheme <- iwanthue(seed=1234, force_init=TRUE)
nta_colors <- color_scheme$hex(nrow(nbhs_map %>%  filter(borough == "MN")))

# Data of tree locations 
tree_locs <- trees %>%
  st_as_sf(coords = c("longitude", "latitude"), crs=4326) %>%
  st_transform("+proj=longlat +ellps=intl +no_defs +type=crs")


# Map of tree locations by neighborhood
tree_locs_map_plot <- ggplot() + 
  geom_sf(data = nbhs_map,
          fill="#E8EAED", color="grey") +
  stat_sf_coordinates(data = tree_locs, 
                      aes(color = paste(nta, nta_name, sep=": ")),
                      size=0.001
  ) +
  stat_sf_coordinates(data = nbhs_map %>% filter(borough=="MN", nta!="MN99"),
                      color="grey25", size=0.25) +
  geom_sf(data = nbhs_map %>% filter(borough=="MN", nta!="MN99"),
          color="grey25",
          alpha=0.1) + 
  theme(legend.position = c(0.024, 0.5),
        legend.justification=0.0,
        legend.key.width = unit(2.5, 'mm'),
        legend.key.height = unit(1.8, 'mm'), 
        legend.direction="vertical",
        legend.background= element_roundrect(r = grid::unit(0.02, "snpc"),
                                             fill=alpha("#FFFFFF", 0.90)),
        legend.key = element_rect(fill=NA),
        legend.text = element_text(margin = margin(r=5, unit="pt"),
                                   color="#65707C",
                                   family="sans serif"),
        legend.title = element_text(face="bold",
                                    color="#65707C",
                                    size=8.5,
                                    family="sans serif"),
        axis.title = element_text(color="#65707C",
                                  face="bold",
                                  family="sans serif"),
        axis.text = element_text(color="#65707C",
                                 size=7,
                                 family="sans serif"),
        axis.text.x = element_text(angle=90,
                                   vjust=0.5,
                                   hjust=1),
        axis.line = element_line(colour="grey",
                                 linewidth=0.5),
        panel.grid.major = element_line(color="grey",
                                        linetype="dashed",
                                        linewidth=0.25),
        panel.border = element_rect(color="grey40",
                                    fill=NA),  
        panel.spacing = unit(2, "lines"),
        panel.background  = element_roundrect(r = grid::unit(0.001, "snpc"),
                                              fill=alpha("#9CC0F9", 1)),
    rect = element_rect(fill = "transparent"),
        plot.title = element_text(color="#65707C",
                                  vjust=10,
                                  size=14,
                                  family="sans serif")) +
  labs(x="", y="", color="    Code: Name") +
  ggtitle("Fig. 1: Map of the Tree Locations by Neighborhood in Manhattan") +
  scale_x_continuous(limits = c(-74.25, -73.89), 
                     breaks = seq(-74.25, -73.89, by=0.02)) +
  scale_y_continuous(limits = c(40.68, 40.88), 
                     breaks = seq(40.68, 40.88, by=0.02)) +
  guides(color = guide_legend(ncol=1,
                              override.aes = list(shape=15,
                                                  size=2.5
                              ))) +
  ggrepel::geom_text_repel(data = nbhs_map %>% filter(borough == "MN", nta != "MN99"),
                            aes(label = nta, geometry = geometry),
                            stat="sf_coordinates",
                            min.segment.length=0,
                            size=2,
                            label.size=NA,
                fontface="bold"
              ) +
  coord_sf(xlim = c(-74.25, -73.89), ylim = c(40.68, 40.88)) +
  scale_color_manual(values = nta_colors)

While trees seem to cover much each of Manhattan’s 28 neighborhoods, some of the southern ones, including MN13, MN17, MN24, MN25, MN27, MN28, and MN50, have empty areas. Interestingly, four of these aforementioned neighborhoods (indicated by *) are among the top ten in terms of shape size, which are:

  1. Hudson Yards-Chelsea-Flatiron-Union Square (MN13)*
  2. Upper West Side (MN12)
  3. Midtown-Midtown South (MN17)*
  4. Central Harlem North-Polo Grounds (MN03)
  5. West Village (MN23)
  6. SoHo-TriBeCa-Civic Center-Little Italy (MN24)*
  7. East Harlem North (MN34)
  8. Lower East Side (MN28)*
  9. Washington Heights South (MN36)
  10. Washington Heights North (MN35)

Fig. 1: Map of the Tree Locations by Neighborhood in Manhattan

2.1.1.2. Tree Counts by Neighborhood
# Table for Top 10 Tree-Producing Neighborhoods
for_table_nbh_tree_cnts <- nbh_tree_cnts %>%
  slice(1:10) %>%
  rownames_to_column("rank") %>%
  mutate(number_of_trees = prettyNum(number_of_trees, big.mark=","),
           percentage = label_percent(accuracy=0.01)(proportion)) %>%
  select(-proportion)

# Order by number of trees
nbhs_map$nta_and_tree_cnt <- factor(
    nbhs_map$nta_and_tree_cnt,
       levels = nbhs_map$nta_and_tree_cnt,
       ordered=TRUE
)

# Map of NTAs' tree counts
nbhs_tree_cnts_map_plot <- ggplot() + 
  geom_sf(data = nbhs_map %>% filter(borough != "MN" | nta == "MN99"),
            fill="#E8EAED", color="grey") +
  geom_sf(data = nbhs_map %>% filter(borough == "MN", nta != "MN99"),
            aes(fill = number_of_trees,
                color = nta_and_tree_cnt
           )) + 
    stat_sf_coordinates(data = nbhs_map %>% filter(nta %in% for_table_nbh_tree_cnts$nta),
                        color="grey25", size=0.5) +
    theme(legend.position = #c(0.7, 0.8),
          c(0.369, 0.5), 
          #c(0.025, 0.5),
          legend.justification=0.0,
          legend.key.width = unit(2.5, 'mm'),
        legend.key.height = unit(1.8, 'mm'), 
          legend.direction="vertical",
          legend.background = element_roundrect(r = grid::unit(0.02, "snpc"),
                                               fill = alpha("#FFFFFF", 0.90)),
          legend.key = element_rect(fill=NA),
          legend.text = element_text(margin = margin(r=5, unit="pt"),
                                     size=7.9,
                                   color="#65707C",
                                     family="sans serif"),
          legend.title = element_text(face="bold",
                                      color="#65707C",
                                      size=8.5,
                                      family="sans serif"),
          axis.title = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text = element_text(color="#65707C",
                                   size=7,
                                   family="sans serif"),
          axis.text.x = element_text(angle=90,
                                     vjust=0.5,
                                     hjust=1),
          axis.line = element_line(colour="grey",
                                   linewidth=0.5),
          panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.border = element_rect(color="grey40",
                                      fill=NA),  
          panel.spacing = unit(2, "lines"),
          panel.background  = element_roundrect(r = grid::unit(0.001, "snpc"),
                                               fill = alpha("#9CC0F9", 1)),
      rect = element_rect(fill = "transparent"),
          plot.title = element_text(color="#65707C",
                                    vjust=10,
                                    size=14,
                                    family="sans serif")) +
     labs(x="", y="", color="   Code - Number of trees : Name"
             ) +
     ggtitle("Fig. 2: Map of the Number of Trees in Manhattan's Neighborhoods") +
  scale_x_continuous(expand = c(0.01, 0),
                       limits = c(-74.04, -73.64), 
                       breaks = seq(-74.04, -73.64, by=0.02)) +
  scale_y_continuous(expand = c(0.01, 0),
                       limits = c(40.68, 40.88), 
                       breaks = seq(40.68, 40.88, by=0.02)) +
  scale_color_manual(values = replicate(28, "grey25")) +
  scale_fill_gradient2(low = muted("499F78"),
                         high = muted("#216968")) +
  ggrepel::geom_text_repel(data = nbhs_map %>% filter(nta %in% for_table_nbh_tree_cnts$nta),
                              aes(label = nta, geometry = geometry),
                              stat="sf_coordinates",
                              min.segment.length=0,
                              label.size=NA,
                              alpha=0.5,
                  fontface="bold"
               ) +
  coord_sf(xlim = c(-74.04, -73.64), ylim = c(40.68, 40.88))     #-74.28, -73.88

# Extract NTA fill colors
color_scheme_2 <- as.data.frame(ggplot_build(nbhs_tree_cnts_map_plot)$data[[2]])$fill

nbhs_tree_cnts_map_plot1 <- nbhs_tree_cnts_map_plot +
  guides(fill = "none",
           color = guide_legend(ncol=1,
                                override.aes = list(color = NA,
                                                    fill = color_scheme_2,
                                                    linewidth=0))
          )

nbh_tree_cnts %>%
  slice(1:10) %>%
  rownames_to_column("rank") %>%
  mutate(number_of_trees = prettyNum(number_of_trees, big.mark=","),
          percentage = label_percent(accuracy=0.01)(proportion)) %>%
  select(-proportion)      

The top ten neighborhoods by tree counts are:

RankNTANTA NameNumber of TreesPercentage
1MN12Upper West Side*5,8079.04%
2MN40Upper East Side–Carnegie Hill4,6167.19%
3MN23West Village*3,8015.92%
4MN03Central Harlem North–Polo Grounds*3,4695.40%
5MN13Hudson Yards–Chelsea–Flatiron–Union Square*2,9314.56%
6MN36Washington Heights South*2,9244.55%
7MN09Morningside Heights2,7044.21%
8MN11Central Harlem South2,6434.11%
9MN35Washington Heights North*2,6124.07%
10MN34East Harlem North*2,5053.90%

Seven of which (indicated by *) are part of the ten largest.

Fig. 2: Map of the Number of Trees in Manhattan's Neighborhoods

2.1.1.3. Trees by Curb Location
# Tree count per location in relation to curb
number_of_trees_per_curb_loc <- merged_trees_and_neighborhoods %>%
  filter(str_detect(nta, "MN") & !(nta == "MN99")) %>%
  group_by(curb_loc) %>%
  summarize(number_of_trees = n()) %>%
  arrange(desc(number_of_trees)) %>%
    mutate(percentage = label_percent(accuracy=0.01)(number_of_trees/length(merged_trees_and_neighborhoods$tree_id)))

on_curb_stat <- number_of_trees_per_curb_loc %>%
    mutate(proportion = number_of_trees/sum(number_of_trees)) %>% 
  filter(proportion == max(abs(proportion)))

# Create a chart for curb location
curb_loc_stacked_bar_plot <- ggplot(number_of_trees_per_curb_loc) + 
  geom_chicklet(aes(x="", y = number_of_trees/sum(number_of_trees),
                      fill = curb_loc), 
                  radius = grid::unit(0.75, "mm"),
                  position="stack") +
  coord_flip() +
  theme(legend.position="right",
          legend.justification="top",
          legend.direction="vertical",
          legend.key.size = unit(0, 'pt'),
          #legend.key = element_rect(fill = NA),
          legend.text = element_text(margin = margin(r = 4, unit = "pt"),
                                     color = "#65707C",
                                     family="sans serif"),
          legend.title = element_text(color = "#65707C",
                                      face="bold",
                                      size = 9,
                                      family="sans serif"),
      axis.title.x = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
      axis.title.y = element_blank(),
          axis.text = element_blank(),
          axis.line = element_blank(),
          axis.ticks = element_blank(),
          panel.grid.minor = element_blank(),
          panel.grid.major = element_blank(),
          panel.background = element_blank(),
      rect = element_rect(fill = "transparent"),
          plot.subtitle = element_text(color="#65707C",
                                    hjust=0.25,
                                    size=10,
                                    family="sans serif"),
          plot.title = element_text(color="#65707C",
                                    hjust=-0.15,
                                    size=14,
                                    family="sans serif"),
      plot.margin = unit(c(0,1,0,1), "cm")) +	
  scale_fill_manual(values = c("#875826",
                                 "#10401B")) + 
  ggtitle("\nFig. 3: Proportional Stacked Bar Graph of Tree Bed Location ",
            subtitle="  (in relation to the Curb)\n") +
  labs(y="\n%  \n(Number of trees)\n", fill="Location:  ") +
    guides(fill = guide_legend(nrow=2,
                               reverse=TRUE,
                               override.aes = list(shape = 15,
                                                   size = 4))) +
  scale_x_discrete(expand = c(0.01, 0)) +
  geom_text(data = on_curb_stat,
                             aes(label = paste(label_percent(accuracy=0.01)(proportion),
                                       "\n (", prettyNum(number_of_trees,
                                                  big.mark=","),")",
                                       sep=""),
                                 x = "",
                                 y = 0.50 * proportion - 0.075),
                            size=5, color="white", hjust=1)

Majority or 93.31% (59,932) of the tree beds are located on curb, while the remaining 6.69% (4,297) are located offset from curb.

Fig. 3: Proportional Stacked Bar Graph of Tree Bed Location

2.1.1.4. Tree Curb Location by Neigborhood
### Characteristics by Neighborhood

# Curb location per neighborhood
curb_loc_per_nbh <- merged_trees_and_neighborhoods %>% 
	filter(str_detect(nta, "MN") & !(nta == "MN99")) %>%
	group_by(nta, nta_name, curb_loc) %>%
	summarize(number_of_trees=n(), .groups="keep") %>%
	group_by(nta) %>%
	mutate(proportion = number_of_trees/sum(number_of_trees),
           percentage = label_percent(accuracy=0.01)(proportion)) %>%
	arrange(desc(proportion)) %>%
	ungroup()

# Higher between OnCurb and OffsetFromCurb per neighborhood
oncurb_vs_offset_per_nbh <- curb_loc_per_nbh %>% 
	group_by(nta) %>%
	filter(proportion == max(abs(proportion)))

# Order by NTA
curb_loc_per_nbh$nta_name <- factor(
    curb_loc_per_nbh$nta_name,
       levels = rev(unique(curb_loc_per_nbh$nta_name)),
       ordered=TRUE
)

# Table of Top 10 NTAs with the highest % of on-curb-located trees
top_on_curb <- curb_loc_per_nbh %>%
	filter(curb_loc=="OnCurb") %>%
	top_n(10, proportion) %>%
	arrange(desc(proportion)) %>%
    rownames_to_column("rank") %>%
	rename(number_of_on_curb_trees = number_of_trees)

# Table of Top 10 NTAs with the highest % of offset-from-curb-located trees
top_offset <- curb_loc_per_nbh %>%
	filter(curb_loc=="OffsetFromCurb") %>%
	top_n(10, proportion) %>%
	arrange(desc(proportion)) %>%
    rownames_to_column("rank") %>%
	rename(number_of_offset_from_curb_trees = number_of_trees)

# Proportional stacked bar graph of curb location per neighborhood
curb_loc_per_nbh_stacked_bar_plot <- ggplot(curb_loc_per_nbh) + 
	geom_chicklet(aes(x = nta_name, y = proportion*100, fill = curb_loc), 
                  radius = grid::unit(0.75, "mm"), position="stack") +
	coord_flip() +
	theme(legend.position="right",
          legend.justification="top",
          legend.direction="vertical",
          legend.key.size = unit(0, "pt"),
          legend.key = element_rect(fill=NA),
          legend.text = element_text(margin = margin(r = 4, unit = "pt"),
                                     color="#65707C",
                                     family="sans serif"),
          legend.title = element_text(color="#65707C",
                                      face="bold",
                                      size=9,
                                      family="sans serif"),
		  axis.title = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text.x = element_text(color="#65707C",
                                   size=6,
                                   family="sans serif"),
          axis.text.y = element_text(color="#65707C",
                                   size=10,
                                   family="sans serif"),
          axis.line = element_line(colour="grey",
                                   linewidth=0.5),
          panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.background = element_blank(),
          plot.subtitle = element_text(color="#65707C",
                                    hjust=5.38,
                                    size=10,
                                    family="sans serif"),
          plot.title = element_text(color = "#65707C",
                                    hjust = 0.709,
                                    size= 12.2,
                                    family = "sans serif")) +
	scale_fill_manual(values = c("#875826",
                                 "#10401B")) +     
	ggtitle("\nFig. 4: Proportional Stacked Bar Graph of Each Neighborhood's Tree Bed Location",
            subtitle="               (in relation to the Curb)\n") +
	labs(x="\nNTA name \n", y="\nNTA code - % of on trees\n", fill="Location: ") +
    guides(fill = guide_legend(ncol=1,
                               reverse=TRUE,
                               override.aes = list(shape = 15,
                                                   size = 4))) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 100, by=10)) +
	ggrepel::geom_text_repel(data = oncurb_vs_offset_per_nbh,
                             aes(label = paste(nta, " - ", 
                                               label_percent(accuracy=0.01)(proportion),
                                       sep=""),
                                 x = nta_name,
                                 y = ifelse(nta=="MN50", 100*proportion+22,
                                            100*proportion-22)),
                             size=2.2, color="white", hjust=1)

Twenty neighborhoods have at least 90% of their trees being on curb, while 27 have at least 75%. The ten neighborhoods with the highest percentage of trees located on-curb are:

RankNTANTA NameNumber of On-Curb TreesPercentage
1MN22East Village1,53399.42%
2MN06Manhattanville89098.67%
3MN21Gramercy1,11997.99%
4MN23West Village3,72197.90%
5MN13Hudson Yards–Chelsea–Flatiron–Union Square2,86097.58%
6MN32Yorkville2,12797.57%
7MN15Clinton1,90697.54%
8MN35Washington Heights North2,52896.78%
9MN31Lenox Hill–Roosevelt Island2,19896.53%
10MN34East Harlem North2,41096.21%

Only Stuyvesant Town-Cooper Village has the majority of its trees being offset from curb. Including it, the neighborhoods with the highest percentage of trees located offset from curb are:

RankNTANTA NameNumber of Offset-from-Curb TreesPercentage
1MN50Stuyvesant Town–Cooper Village24254.88%
2MN25Battery Park City–Lower Manhattan28522.02%
3MN27Chinatown23916.40%
4MN09Morningside Heights41115.20%
5MN33East Harlem South22011.31%
6MN28Lower East Side20210.54%
7MN24SoHo–TriBeCa–Civic Center–Little Italy22010.14%
8MN12Upper West Side58210.02%
9MN14Lincoln Square1939.44%
10MN40Upper East Side–Carnegie Hill3156.82%

Fig. 4: Proportional Stacked Bar Graph of Each Neighborhood's Tree Bed Location

2.1.2. Biological

2.1.2.1. Tree Size
# Species
nta_spc <- as.data.frame.matrix(table(trees$nta, trees$spc_common))

# Tree size (in terms of trunk diameter)
nta_tree_dbh <- as.data.frame.matrix(table(trees$nta, trees$tree_dbh)) %>%
  rename_with( ~ paste0(.x, "_tree_dbh"))

# Summary statistics of the trunk diameter
tree_dbh_stats <- data.frame(N = length(trees$tree_dbh),
                 mean = mean(trees$tree_dbh),
                             sd = sd(trees$tree_dbh),
                             min = min(trees$tree_dbh),
                             first_quartile = quantile(trees$tree_dbh, probs = 0.25),
                             median = median(trees$tree_dbh),
                             second_quartile = quantile(trees$tree_dbh, probs = 0.75),
                             max = max(trees$tree_dbh))
row.names(tree_dbh_stats) <- "tree_dbh" 

# Density curve for 'tree_dbh'
tree_dbh_dist_plot <- ggplot(trees, aes(x = tree_dbh)) + 
  geom_histogram(aes(y = after_stat(density)),
                   binwidth=1.1,
                   color=1,
                   fill="#5FBD5F") +
  geom_density(linewidth=0.85,
                 linetype=1,
                 colour = muted("5FBD5F"),
                 alpha=0.5) +

# Plot mean and median
geom_vline(aes(xintercept = mean(tree_dbh)), col="red", size=0.6) +
geom_vline(aes(xintercept = median(tree_dbh)), col="blue", size=0.6) +

     theme(axis.title = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text = element_text(color="#65707C",
                                   size=12,
                                   family="sans serif"),
          axis.line = element_line(colour="grey",
                                   linewidth=0.5),
          panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.background = element_blank(),
          plot.subtitle = element_text(color="#65707C",
                                    hjust=0.15,
                                    size=10,
                                    family="sans serif"),
          plot.title = element_text(color="#65707C",
                                    hjust=0.20,
                                    size=14,
                                    family="sans serif")) +
  ggtitle("\nFig. 5: Distribution of the Trunk Diameter") +
  labs(x="\nTrunk diameter in inches\n", y="\nDensity\n",
         subtitle="                (measured at 54 inches above the ground)\n") +
  scale_x_continuous(expand = c(0.01, 0), 
                       limits = c(0, 105),
                       breaks = seq(0, 105, by=10)) +
  scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0, 0.12), 
                       breaks = seq(0, 0.12, by=0.02))

In terms of trunk diameter, the mean size of the tree population (red line in Fig. 5) is 8.6312 inches, with a standard deviation of 5.5906. Furthermore, its distribution is positively skewed, implying that the majority of trees have trunk diameters closer to the lower bound. In this case, we can use the median (blue line) of 8 inches (with an IQR of 7) as a better measure of central tendency (and spread).

Fig. 5: Distribution of the Trunk Diameter

# Status and health 
pop_status <- as.data.frame(table(trees$status)) %>%
  mutate(attribute = "status", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

pop_health <- as.data.frame(table(trees$health)) %>%
  mutate(attribute = "health", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything()) %>%
  arrange(desc(proportion))

# Root problems
pop_root_stone <- as.data.frame(table(trees$root_stone)) %>%
  mutate(attribute = "root_stone", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

pop_root_grate <- as.data.frame(table(trees$root_grate)) %>%
  mutate(attribute = "root_grate", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

pop_root_other <- as.data.frame(table(trees$root_other)) %>%
  mutate(attribute = "root_other", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

# Trunk problems
pop_trunk_wire <- as.data.frame(table(trees$trunk_wire)) %>%
  mutate(attribute = "trunk_wire", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

pop_trnk_light <- as.data.frame(table(trees$trnk_light)) %>%
  mutate(attribute = "trnk_light", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

pop_trnk_other <- as.data.frame(table(trees$trnk_other)) %>%
  mutate(attribute = "trnk_other", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

# Branch problems
pop_brch_light <- as.data.frame(table(trees$brch_light)) %>%
  mutate(attribute = "brch_light", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

pop_brch_shoe <- as.data.frame(table(trees$brch_shoe)) %>%
  mutate(attribute = "brch_shoe", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())
  
pop_brch_other <- as.data.frame(table(trees$brch_other)) %>%
  mutate(attribute = "brch_other", proportion = Freq/sum(Freq)) %>%
  rename(category = Var1, number_of_trees = Freq) %>%
  select(attribute, everything())

# Tree population's attributes
pop_attributes <- bind_rows(pop_status,
                            pop_health,
                            pop_root_stone,
                            pop_root_grate,
                            pop_root_other,
                            pop_trunk_wire,
                            pop_trnk_light,
                            pop_trnk_other,
                            pop_brch_light,
                            pop_brch_shoe,
                            pop_brch_other) %>%
                  mutate(percentage = label_percent(accuracy = 0.01)(proportion))  		

# Status and health 
nta_status <- as.data.frame.matrix(table(trees$nta, trees$status)) %>%
  rename_with( ~ paste0(.x, "_status"))
nta_health <- as.data.frame.matrix(table(trees$nta, trees$health)) %>%
  rename_with( ~ paste0(.x, "_health"))

# Root problems
nta_root_stone <- as.data.frame.matrix(table(trees$nta, trees$root_stone)) %>%
  rename_with( ~ paste0(.x, "_root_stone"))
nta_root_grate <- as.data.frame.matrix(table(trees$nta, trees$root_grate)) %>%
  rename_with( ~ paste0(.x, "_root_grate"))
nta_root_other <- as.data.frame.matrix(table(trees$nta, trees$root_other)) %>%
  rename_with( ~ paste0(.x, "_root_other"))

# Trunk problems
nta_trunk_wire <- as.data.frame.matrix(table(trees$nta, trees$trunk_wire)) %>%
  rename_with( ~ paste0(.x, "_trunk_wire"))
nta_trnk_light <- as.data.frame.matrix(table(trees$nta, trees$trnk_light)) %>%
  rename_with( ~ paste0(.x, "_trnk_light"))
nta_trnk_other <- as.data.frame.matrix(table(trees$nta, trees$trnk_other)) %>%
  rename_with( ~ paste0(.x, "_trnk_other"))

# Branch problems
nta_brch_light <- as.data.frame.matrix(table(trees$nta, trees$brch_light)) %>%
  rename_with( ~ paste0(.x, "_brch_light"))
nta_brch_shoe <- as.data.frame.matrix(table(trees$nta, trees$brch_shoe)) %>%
  rename_with( ~ paste0(.x, "_brch_shoe"))
nta_brch_other <- as.data.frame.matrix(table(trees$nta, trees$brch_other)) %>%
  rename_with( ~ paste0(.x, "_brch_other"))

# Table of biological attributes per species
nta_bio <- bind_cols(list(nta_tree_dbh,
                          nta_status,
                          nta_health,
                          nta_root_stone,
                          nta_root_grate,
                          nta_root_other,
                          nta_trunk_wire,
                          nta_trnk_light,
                          nta_trnk_other,
                          nta_brch_light,
                          nta_brch_shoe,
                          nta_brch_other)) %>%
  rownames_to_column("nta")              		  

# Highest category per attribute
pop_attributes_highest_per_category <- pop_attributes %>%
  group_by(attribute) %>%
  filter(proportion == max(abs(proportion)))

# Order by attributes 
pop_attributes$attribute <- factor(
    pop_attributes$attribute,
       levels = rev(unique(pop_attributes$attribute)),
       ordered=TRUE
)

# Order by categories 
pop_attributes$category <- factor(
    pop_attributes$category,
       levels = c("Dead", "Alive", "Fair", "Poor", "Good", "Yes", "No"),
       ordered=TRUE
)

pop_attributes_stacked_bar_plot <- ggplot(pop_attributes) + 
  geom_chicklet(aes(x = attribute, y = proportion*100, fill = category), 
                  radius = grid::unit(0.75, "mm"), position="stack") +
  coord_flip() +
  theme(legend.position = "right",
          legend.justification="top",
          legend.direction="vertical",
          legend.key.size = unit(0, "pt"),
          legend.key = element_rect(fill = NA),
          legend.text = element_text(margin = margin(r = 4, unit = "pt"),
                                     color = "#65707C",
                                     family="sans serif"),
          legend.title = element_text(color = "#65707C",
                                      face = "bold",
                                      size = 9,
                                      family="sans serif"),
      axis.title = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text = element_text(color="#65707C",
                                   size=12,
                                   family="sans serif"),
          axis.line = element_line(colour="grey",
                                   linewidth=0.5),
          panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.background = element_blank(),
          plot.title = element_text(color = "#65707C",
                                    hjust = 0.715,
                                    size= 13.75,
                                    family = "sans serif")) +
  scale_x_discrete(labels=c("Other problems (branch)",
                              "Shoes (branch)",
                              "Lights or wires (branch) ",
                              "Other problems (trunk)",
                              "Lighting installed (trunk)",
                              "Wires or rope (trunk)",
                              "Other problems (root)",
                              "Metal grates (root)",
                              "Paving stones (root)",
                              "Health",
                              "Status"))+
  scale_fill_manual(values = c("grey40",
                                 "#10401B",
                                 "#89E7B3",
                 "#40C17E",
                                 "#1F9153",
                                 "#9F2305",
                                 "#4E7A61"),
                     labels = c("Dead", "Alive", "Poor",  "Fair", "Good", "Yes", "No")) +
  ggtitle("\nFig. 6: Proportional Stacked Bar Graph of the Tree Population's Attributes\n") +
  labs(x="\nAttribute \n", y="\n%  \n(Number of trees) \n", fill="Category: ") +
    guides(fill = guide_legend(ncol=1,
                               override.aes = list(shape = 15,
                                                   size = 4))) +
  scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 100, by=10)) +
  ggrepel::geom_text_repel(data = pop_attributes_highest_per_category,
                             aes(label = paste(percentage,
                                       "\n (", prettyNum(number_of_trees,
                                                  big.mark=","),")",
                                       sep=""),
                                 x = attribute,
                                 y = 100*proportion-20),
                             size=3, color="white", hjust=1)

Nearly all of the trees in Manhattan have an “Alive” status, and majority are in a “Good” health condition. On the other hand, the minority of trees have problems with their roots, trunks, and branches. The most notable among these respective tree parts are caused by paving stones in the tree bed; trunk problems other than by wires/ropes and installed lighting; and branch problems other than by lights/wires and shoes.

Fig. 6: Proportional Stacked Bar Graph of the Tree Population's Attributes

2.2. Tree Species

Using spatial, descriptive, and correlation analyses, the following information outlines the biodiversity, biology, and ranking in terms of desirable traits of the tree species in Manhattan:

### Characteristics by Species

nbh_spc_long <- nta_spc %>%
  rownames_to_column("nta") %>% 
  pivot_longer(cols = 2:129, 
                 names_to = "spc_common",
                 values_to = "number_of_trees") %>%
  inner_join(trees %>% select(nta, nta_name) %>% distinct(nta, nta_name), by = "nta")

top_spc_per_nbh <- nbh_spc_long %>%
  group_by(nta) %>%
  top_n(1, number_of_trees) %>%
  arrange(nta, desc(number_of_trees)) %>%
  select(contains("nta"), everything()) %>%
  mutate(percentage = label_percent(accuracy=0.01)(
           number_of_trees/length(trees$tree_id)))

top_spc_per_nbh_short <- top_spc_per_nbh %>%
  group_by(spc_common) %>% 
    mutate(nta = paste0(nta, collapse = ", "),
           nta_name = paste0(nta_name, collapse = ", ")) %>%
  count(nta, nta_name, spc_common) %>%
  arrange(desc(n)) %>%
    select(nta, nta_name, spc_common, n) %>%
  mutate(percentage = label_percent(accuracy=0.01)(n/28)) %>% 
  rename(number_of_nta = n, most_common_spc = spc_common) 

# Counts of neighborhood for the most common species
spc_in_top_ten_per_nbh <- nbh_spc_long %>%
  group_by(nta) %>%
  top_n(10, number_of_trees) %>%
  arrange(nta, desc(number_of_trees)) %>%
  select(contains("nta"), everything()) %>%
  ungroup() %>%
  count(spc_common) %>%
  mutate(percentage = label_percent(accuracy=0.01)(n/28)) %>% 
  arrange(desc(n)) %>%   
  rename(number_of_nta = n)

## Location

# Location in relation with the curb 
spc_curb_loc <- as.data.frame.matrix(table(trees$spc_common, trees$curb_loc)) %>%
  rename_with( ~ paste0(.x, "_loc"))

## Biology

# Tree size (in terms of trunk diameter)
spc_tree_dbh <- as.data.frame.matrix(table(trees$spc_common, trees$tree_dbh)) %>%
  rename_with( ~ paste0(.x, "_tree_dbh"))

# Status and health 
spc_status <- as.data.frame.matrix(table(trees$spc_common, trees$status)) #%>%
  #rename_with( ~ paste0(.x, "_status"))
spc_health <- as.data.frame.matrix(table(trees$spc_common, trees$health)) #%>%
  #rename_with( ~ paste0(.x, "_health"))

# Root problems
spc_root_stone <- as.data.frame.matrix(table(trees$spc_common, trees$root_stone)) %>%
  rename_with( ~ paste0(.x, "_root_stone"))
spc_root_grate <- as.data.frame.matrix(table(trees$spc_common, trees$root_grate)) %>%
  rename_with( ~ paste0(.x, "_root_grate"))
spc_root_other <- as.data.frame.matrix(table(trees$spc_common, trees$root_other)) %>%
  rename_with( ~ paste0(.x, "_root_other"))

# Trunk problems
spc_trunk_wire <- as.data.frame.matrix(table(trees$spc_common, trees$trunk_wire)) %>%
  rename_with( ~ paste0(.x, "_trunk_wire"))
spc_trnk_light <- as.data.frame.matrix(table(trees$spc_common, trees$trnk_light)) %>%
  rename_with( ~ paste0(.x, "_trnk_light"))
spc_trnk_other <- as.data.frame.matrix(table(trees$spc_common, trees$trnk_other)) %>%
  rename_with( ~ paste0(.x, "_trnk_other"))

# Branch problems
spc_brch_light <- as.data.frame.matrix(table(trees$spc_common, trees$brch_light)) %>%
  rename_with( ~ paste0(.x, "_brch_light"))
spc_brch_shoe <- as.data.frame.matrix(table(trees$spc_common, trees$brch_shoe)) %>%
  rename_with( ~ paste0(.x, "_brch_shoe"))
spc_brch_other <- as.data.frame.matrix(table(trees$spc_common, trees$brch_other)) %>%
  rename_with( ~ paste0(.x, "_brch_other"))

# Total number of identified species (Richness)
n_species <- trees %>%
  group_by(spc_common) %>%
  summarize(number_of_trees_per_species = n()) %>%
  filter(!is.na(spc_common)) %>%
  summarize(number_of_identified_species = n())

# Total number of trees with identified species (N_I) and unidentified species (N_U)
N_I_and_U <- trees %>%
  filter(is.na(spc_common)) %>%
  summarize(number_of_trees_with_unidentified_species = n()) %>%
  mutate(number_of_trees_with_identified_species = nrow(trees) - number_of_trees_with_unidentified_species) 

# Top 10 NTAs with the highest species richness
top_ten_nbh_rchns <- nbh_rchns %>%
  slice(1:10) %>%
  rownames_to_column("rank")

# Order by richness
nbhs_map$nta_and_rchns <- factor(
    nbhs_map$nta_and_rchns,
       levels = (nbhs_map %>% arrange(desc(richness)))$nta_and_rchns,
       ordered = TRUE
)

# Map of NTAs' richness
nbh_rchns_map_plot <- ggplot() + 
  geom_sf(data = nbhs_map %>% filter(borough != "MN" | nta == "MN99"),
            fill="#E8EAED", color="grey") +
  geom_sf(data = nbhs_map %>% filter(borough == "MN", nta != "MN99"),
            aes(fill = richness,
                color = nta_and_rchns
               )
           ) + 
    stat_sf_coordinates(data = nbhs_map %>% filter(borough == "MN", nta != "MN99") %>%
                        inner_join(nbh_rchns, by = c("nta", "nta_name")) %>%
                          filter(nta %in% top_ten_nbh_rchns$nta),
                        color="grey25", size = 0.5) +
    theme(legend.position = c(0.3518, 0.5), 
          legend.justification=0.0,
          legend.key.width = unit(2.5, 'mm'),
        legend.key.height = unit(1.8, 'mm'), 
          legend.direction="vertical",
          legend.background = element_roundrect(r = grid::unit(0.02, "snpc"),
                                               fill = alpha("#FFFFFF", 0.90)),
          legend.key = element_rect(fill=NA),
          legend.text = element_text(margin = margin(r=5, unit="pt"),
                                   color="#65707C",
                                     family="sans serif"),
          legend.title = element_text(face="bold",
                                      color="#65707C",
                                      size=8.5,
                                      family="sans serif"),
          axis.title = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text = element_text(color="#65707C",
                                   size=7,
                                   family="sans serif"),
          axis.text.x = element_text(angle=90,
                                     vjust=0.5,
                                     hjust=1),
          axis.line = element_line(colour="grey",
                                   linewidth=0.5),
          panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          
          panel.border = element_rect(color="grey40",
                                      fill=NA),  
          panel.spacing = unit(2, "lines"),
          panel.background  = element_roundrect(r = grid::unit(0.001, "snpc"),
                                               fill = alpha("#9CC0F9", 1)),
          plot.title = element_text(color="#65707C",
                                    hjust=1.8,
                                    vjust=10,
                                    size=14,
                                    family="sans serif")) +
     labs(x="", y="", color="    Code - Richnesss : Name"
             ) +
     ggtitle("Fig. 7: Map of Tree Species Richness of Manhattan's Neighborhoods") +
  scale_x_continuous(expand = c(0.01, 0),
                       limits = c(-74.04, -73.64), 
                       breaks = seq(-74.04, -73.64, by=0.02)) +
  scale_y_continuous(expand = c(0.01, 0),
                       limits = c(40.68, 40.88), 
                       breaks = seq(40.68, 40.88, by=0.02)) +
  scale_color_manual(values = replicate(28, "grey25")) +
  scale_fill_gradient2(low = "#E3EDE5",
                         high = "#068409") +
  ggrepel::geom_label_repel(data = nbhs_map %>% filter(nta %in% top_ten_nbh_rchns$nta),
                              aes(label = nta, geometry = geometry),
                              stat="sf_coordinates",
                              min.segment.length=0,
                              label.size=NA,
                              alpha=0.5) +
  coord_sf(xlim = c(-74.04, -73.64), ylim = c(40.68, 40.88))     

# Extract NTA fill colors
color_scheme_3 <- as.data.frame(ggplot_build(nbh_rchns_map_plot)$data[[2]])$fill

nbh_rchns_map_plot2 <- nbh_rchns_map_plot +
  guides(fill = "none",
           color = guide_legend(ncol=1,
                                override.aes = list(color = NA,
                                                    fill = color_scheme_3,
                                                    linewidth=0))
          )

2.2.1. Biodiversity

2.2.1.1. Richness

Richness is referred to as the number of species within a defined region. With respect to Manhattan, 128 species were identified among \({N_{I} =}\) 62,428 trees, while the remaining \({N_{U} =}\) 1,801 have species which are unidentified in the census. In terms of the neighborhoods, the ten with the highest richness (of identified species) are:

RankNTANTA NameRichness
1MN35Washington Heights North81
2MN28Lower East Side78
3MN36Washington Heights South77
4MN23West Village76
5MN03Central Harlem North–Polo Grounds75
6MN04Hamilton Heights73
7MN12Upper West Side73
8MN40Upper East Side–Carnegie Hill73
9MN11Central Harlem South71
10MN22East Village68

Fig. 7: Map of Tree Species Richness of Manhattan's Neighborhoods

2.2.1.2. Abundance
# Species abundance and relative abundance
spc_abd <- trees %>% 
  filter(spc_common != "null") %>%
  group_by(spc_common) %>%
  summarize(abundance = n()) %>%  
  ungroup() %>%
  mutate(relative_abundance = abundance/sum(abundance)) %>%
  arrange(desc(abundance))

# Species abundance and relative abundance by NTA
spc_abd_nbh <- nbh_spc_long %>%
  group_by(nta, nta_name) %>%
  filter(!(number_of_trees == 0)) %>%
  rename(abundance_wrt_nta = number_of_trees) %>%
  select(starts_with("nta"), spc_common, everything()) %>%
  mutate(relative_abundance_wrt_nta = label_percent(accuracy=0.01)(abundance_wrt_nta/sum(abundance_wrt_nta))) %>% 
  arrange(nta, desc(abundance_wrt_nta)) %>%
  ungroup()

# Table for Top 10 Most Abundant Species
for_table_spc_abd <- spc_abd %>%
  slice(1:10) %>%
  rownames_to_column("rank") %>%
  mutate(abundance = prettyNum(abundance,big.mark=","),
           perc_relative_abundance = label_percent(accuracy=0.01)(relative_abundance))

# Bar graph for Top 25 tree species
top_species_bar_plot <- ggplot(spc_abd %>% slice(1:25)) + 
  geom_chicklet(aes(x = fct_reorder(spc_common,
                                    abundance),
                      y = abundance), 
                  fill="#10401B",
                  radius = grid::unit(1, "mm"), position="stack") +
  coord_flip() +
  theme(legend.position="none",
          axis.title = element_text(color = "#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text = element_text(color = "#65707C",
                                   size=12,
                                   family="sans serif"),
          axis.title.x = element_text(margin=margin(20,0,10,0)),
          axis.title.y = element_text(margin=margin(0,20,0,10)),
          axis.line = element_line(colour = "grey",
                                   linewidth = 0.5),
          panel.grid.major = element_line(color = "grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.background = element_blank(),
          plot.title = element_text(color = "#65707C",
                                    hjust = 1.03,
                                    vjust = 4,
                                    size= 14,
                                    family = "sans serif",
                                    margin=margin(0,0,20,0))) +
  ggtitle("
\nFig. 8: Bar Graph of the 25 Most Abundant Tree Species in Manhattan ") +
  labs(x="Common name of the species", y="Abundance (% relative abundance)") +
  scale_y_continuous(expand = c(0.01, 0), limits = c(0,13500),
                      breaks = seq(0, 13500, by=2000)) +
  geom_text(aes(label = paste(prettyNum(abundance, big.mark=","),
                                " (", label_percent(accuracy=0.01)(relative_abundance),")",
                                sep=""),
                                 x = spc_common,
                                 y = ifelse(between(rank(desc(abundance)),3,10), abundance-807.5,
                                           ifelse(between(rank(desc(abundance)),2,2), abundance-880,
                                           ifelse(between(rank(desc(abundance)),1,1), abundance-980,
                                           ifelse(between(rank(desc(abundance)),11,11), abundance+770,
                                           abundance+670)))),
                  color = ifelse(between(rank(desc(abundance)),1,10), "white",
                                           "#65707C")),
              size = 2) +
scale_color_manual(values=c("#65707C","white"))

In this context, abundance is defined as the number of Manhattan trees per species, while relative abundance is the share of trees a certain species has in relation to the total number of trees in Manhattan. Among the 128 and other unidentified tree species in Manhattan, the ten most abundant are:

RankSpecies (Common Name)AbundanceRelative Abundance (%)
1Honeylocust13,17621.11%
2Callery pear7,29711.69%
3Ginkgo5,8599.39%
4Pin oak4,5847.34%
5Sophora4,4537.13%
6London planetree4,1226.60%
7Japanese zelkova3,5965.76%
8Littleleaf linden3,3335.34%
9American elm1,6982.72%
10American linden1,5832.54%

Fig. 8: Bar Graph of the 25 Most Abundant Tree Species in Manhattan

2.2.1.3. Diversity

To describe the overall species diversity in Manhattan, a quantitative measure called Simpson’s Diversity Index (SDI) is used, which takes into account the species richness and evenness (or the distribution of abundance across the tree species in a community). The formula is given by:

$$ {D} = {1- \frac{\sum \limits _{i=1} ^{128} n_{i}({n_{i}-1})} {N_{I}({N_{I}-1})} } $$

where \({D} =\) Simpson’s Diversity Index (SDI);
           \({n_{i} = i^{th}}\) species abundance;
          \({N_{I} =}\) number of trees with identified species = 62,428

# Simpson's Diversity Index (SDI)
mnh_sdi <- spc_abd %>%
  filter(!is.na(spc_common)) %>%
   select(-relative_abundance) %>%
   mutate(numerator = abundance*(abundance-1)) %>%
   summarize(SDI = 1-(sum(numerator)/(sum(abundance)*(sum(abundance)-1))),
               number_of_trees = sum(abundance),
               richness = n())

With that, the computed SDI value is 0.909. This means that there is a very high diversity of tree species in Manhattan, and the chance of distinct species among two randomly selected trees from a sample is 90.9%.

2.2.2. Biology

2.2.2.1. Tree Size
# Summary statistics of species' tree dbh
spc_tree_dbh_stats <- trees %>% 
  group_by(spc_common) %>%
  filter(!is.na(spc_common), !is.na(tree_dbh)) %>%
  summarize(abundance = n(),
              mean_tree_dbh = mean(tree_dbh),
              sd_tree_dbh = sd(tree_dbh),
              min_tree_dbh = min(tree_dbh),
              first_quartile_tree_dbh = quantile(tree_dbh, probs=0.25),
              median_tree_dbh = median(tree_dbh),
              third_quartile_tree_dbh = quantile(tree_dbh, probs=0.75),
              max_tree_dbh = max(tree_dbh))  %>%
  arrange(desc(median_tree_dbh))

# Top 25 species in terms of median dbh
top_spc_tree_dbh_stats <- spc_tree_dbh_stats #%>%
  #filter out species with abundances less than the median abundances
#filter(abundance >= median(abundance)) %>%
#select(spc_common, abundance, median_tree_dbh, everything())

# Bar graph for Top 30 tree species
top_spc_dbh_plot <- ggplot(top_spc_tree_dbh_stats %>% slice(1:25)) + 
  geom_chicklet(aes(x = fct_reorder(spc_common,
                                    median_tree_dbh),
                      y = median_tree_dbh), 
                  fill="#10401B",
                  radius = grid::unit(1, "mm"), position="stack") +
  coord_flip() +
  theme(axis.title = element_text(color = "#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text = element_text(color = "#65707C",
                                   size=12,
                                   family="sans serif"),
          axis.title.x = element_text(margin=margin(20,0,10,0)),
          axis.title.y = element_text(margin=margin(0,20,0,10)),
          axis.line = element_line(colour = "grey",
                                   linewidth = 0.5),
          panel.grid.major = element_line(color = "grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.background = element_blank(),
          plot.title = element_text(color="#65707C",
                                    hjust=1.13,
                                    size=14,
                                    family="sans serif"),
          plot.subtitle = element_text(color="#65707C",
                                    hjust=2.02,
                                    size=10,
                                    family="sans serif")) +   
  ggtitle("\nFig. 9: Bar Graph of the Top 25 Largest Tree Species in Manhattan",
            subtitle="(in terms of median trunk diameter at breast height (DBH) of 54 inches)\n") +
  labs(x="\nCommon name of the species\n", y="Trunk diameter in inches\n") +
  scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0, 15.5),
                       breaks = seq(0, 15.5, by=3)) +
  geom_text(aes(label = median_tree_dbh,
                                 x = spc_common,
                                 y = median_tree_dbh-0.4),
              size = 3, color = "white")

Tree sizes of the species were compared through their median trunk diameter at breast height (DBH). Fig. 9 shows the Top 25 largest species in terms of this metric:

Fig. 9: Bar Graph of the Top 25 Largest Tree Species in Manhattan

# Status per species
spc_status <- trees %>% 
  filter(!(is.na(spc_common) | is.na(spc_common))) %>%
  group_by(spc_common, status) %>%
  summarize(number_of_trees = n(), .groups="keep") %>%
  group_by(spc_common) %>%
  mutate(proportion_wrt_spc = number_of_trees/sum(number_of_trees),
           percentage_wrt_spc = label_percent(accuracy=0.01)(proportion_wrt_spc)) %>%
  arrange(proportion_wrt_spc) %>%
  select(-proportion_wrt_spc) %>%
  ungroup()

Out of the 128 species that have been identified, 127 have 100% of their trees being alive, while the remaining one, honeylocust, has 99.99%. As for the health, a numerical value called health index (\(HI\)) was computed for each species. This was done by assigning a number, \({j} ∈ \{1,2,3\}\), to the categories of Poor, Fair, and Good health, respectively, and then using the formula:

\[{HI_{i}} = \frac {\sum \limits _{j=1} ^{3} j{a}_{j}}{3 n_{i}}\]

where \({HI_{i}} =\) health index of the \(i^{th}\) species;
              \({a_{j}} =\) species abundance with respect to the \(j^{th}\) health category;
              \({n_{i}} =\) \({i^{th}}\) species abundance

# Health per species
spc_health <- trees %>% 
  filter(!is.na(spc_common), !is.na(health)) %>%
  group_by(spc_common, health) %>%
  summarize(number_of_trees = n(), .groups="keep") %>%
  group_by(spc_common) %>%
  mutate(proportion = number_of_trees/sum(number_of_trees),
           percentage = label_percent(accuracy=0.01)(proportion),
           health = as.factor(health)) %>%
  arrange(spc_common, desc(proportion)) %>%
  ungroup()

spc_health_index <- spc_health %>%
  group_by(spc_common) %>%
  mutate(health_score = ifelse(health=="Good", 3*number_of_trees,
                                 ifelse(health=="Fair", 2*number_of_trees,
                                        1*number_of_trees)),
          health_index = sum(health_score)/(3*sum(number_of_trees))) %>%
  ungroup() %>%
  select(spc_common, number_of_trees, health_index) %>%
  group_by(spc_common) %>%
  mutate(number_of_trees = sum(number_of_trees)) %>%
  distinct(spc_common, number_of_trees, health_index) %>%
  arrange(desc(health_index)) %>%
  ungroup() %>%
  rename(abundance = number_of_trees)

for_graph_top_spc_health <- spc_health %>%
  filter(spc_common %in% (
        spc_health_index %>%
        #filter out species with abundances less than the median abundances
#filter(abundance >= median(spc_tree_dbh_stats$abundance)) %>% 
                              top_n(25, health_index))$spc_common) %>%
  arrange(desc(proportion))

# Order health per species
for_graph_top_spc_health$health <- factor(
    for_graph_top_spc_health$health,
    levels = c("Poor", "Fair", "Good"),
    ordered = TRUE
)

# Order species by proportion of 'Good' health
for_graph_top_spc_health$spc_common <- factor(
    for_graph_top_spc_health$spc_common,
    levels = rev((for_graph_top_spc_health %>% filter(health == "Good"))$spc_common),
    ordered = TRUE
)

top_spc_health_highest <- for_graph_top_spc_health %>% 
  group_by(spc_common) %>%
  filter(proportion == max(abs(proportion)))

top_spc_health_stacked_bar_plot <- ggplot(for_graph_top_spc_health) + 
  geom_chicklet(aes(x = spc_common, y = proportion*100, fill = health), 
                  radius = grid::unit(0.75, "mm"), position="stack") +
  coord_flip() +
  theme(legend.position = "right",
          legend.justification="top",
          legend.direction="vertical",
          legend.key.size = unit(0, 'pt'),
          legend.key = element_rect(fill = NA),
          legend.text = element_text(margin = margin(r = 4, unit = "pt"),
                                     color = "#65707C",
                                     family="sans serif"),
          legend.title = element_text(color = "#65707C",
                                      face="bold",
                                      size = 9,
                                      family="sans serif"),
      axis.title = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text.x = element_text(color="#65707C",
                                   size=6,
                                   family="sans serif"),
          axis.text.y = element_text(color="#65707C",
                                   size=10,
                                   family="sans serif"),
          axis.line = element_line(colour="grey",
                                   linewidth=0.5),
          panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.background = element_blank(),
          plot.subtitle = element_text(color="#65707C",
                                    hjust=-2.07,
                                    size=10,
                                    family="sans serif"),
          plot.title = element_text(color = "#65707C",
                                    hjust = 0.74,
                                    size= 12,
                                    family = "sans serif")) +
  scale_fill_manual(values = c("#89E7B3",
                 "#40C17E",
                                 "#1F9153")) +     
  ggtitle("\nFig. 10: Proportional Stacked Bar Graph of the Top 25 Healthiest Tree Species",
            subtitle="               (in terms of health index (HI) value)\n") +
  labs(x="\nCommon name of the species\n", y="\n% relative abundance\n", fill="Health: ") +
    guides(fill = guide_legend(ncol=1,
                               override.aes = list(shape = 15,
                                                   size = 4))) +
  scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 100, by=10)) +
  ggrepel::geom_text_repel(data = top_spc_health_highest %>% 
                              inner_join(spc_health_index, by="spc_common"),
                             aes(label = paste("HI: ", round(health_index, digits=2),
                                               ", Good: ", label_percent(
                                                   accuracy=0.01)(proportion), sep=""),
                                 x = spc_common,
                                 y = ifelse(proportion==1, 100*proportion-21.5,
                                            100*proportion-22)),
                             size=2.2, color="white", hjust=1)

Fig. 10 shows the 25 species with the highest HI value as well as the distribution of their relative abundances across health categories.

Fig. 10: Proportional Stacked Bar Graph of the Top 25 Healthiest Tree Species

Paving stones as well as other trunk and branch problems also affect major tree parts (root, trunk, and branch) the most at a species level, similar to what is observed in the analysis of tree population.

Figs. 11 to 13 show the top 25 species with the highest percentage of their trees having at least one problem for each tree part.

# For root problems' graph
spc_root_problems <- trees %>%
  select(spc_common, root_stone:root_other) %>%
  filter(spc_common != "null",
           if_all(-spc_common, ~ .x != "null")) %>%
  mutate(across(root_stone:root_other, ~ ifelse(.x == "Yes", 1, 0)),
           None = ifelse(root_stone == 0 &
                         root_grate == 0 &
                         root_other == 0, 1, 0)) %>%
  group_by(spc_common) %>%
  summarize(none = 100*sum(None)/n(),
              root_stone = 100*sum(root_stone)/n(),
              root_grate = 100*sum(root_grate)/n(),
              root_other = 100*sum(root_other)/n()) %>%
  rename(`Common name of the species` = spc_common,
           `''Paving stones` = root_stone,
           `'Metal grates` = root_grate,
           `Others` = root_other) %>% 
  ungroup() %>%
  filter(rank((none)) <= 25) %>%
  arrange((none)) %>%
    mutate_if(is.numeric, ~(round(., digits = 2))) %>%
  pivot_longer(cols = c(3:5), 
                 names_to = "Root problem",
                 values_to = "% of trees")

Fig. 11: Bar Graph of the Top 25 Tree Species with the Highest Percentage of Trees Having Root Problems

# For trunk problems' graph
spc_trunk_problems <- trees %>%
  select(spc_common, trunk_wire:trnk_other) %>%
  filter(spc_common != "null",
           if_all(-spc_common, ~ .x != "null")) %>%
  mutate(across(trunk_wire:trnk_other, ~ ifelse(.x == "Yes", 1, 0)),
           None = ifelse(trunk_wire == 0 &
                         trnk_light == 0 &
                         trnk_other == 0, 1, 0)) %>%
  group_by(spc_common) %>%
  summarize(none = 100*sum(None)/n(),
              trunk_wire = 100*sum(trunk_wire)/n(),
              trnk_light = 100*sum(trnk_light)/n(),
              trnk_other = 100*sum(trnk_other)/n()) %>%
  rename(`Common name of the species` = spc_common,
           `''Wires or rope` = trunk_wire,
           `'Lighting installed` = trnk_light,
           `Others` = trnk_other) %>% 
  ungroup() %>%
  filter(rank((none)) <= 25) %>%
  arrange((none)) %>%
    mutate_if(is.numeric, ~(round(., digits = 2))) %>%
  pivot_longer(cols = c(3:5), 
                 names_to = "Trunk problem",
                 values_to = "% of trees")

Fig. 12: Bar Graph of the Top 25 Tree Species with the Highest Percentage of Trees Having Trunk Problems

# For branch problems' graph
brch_trunk_problems <- trees %>%
  select(spc_common, brch_light:brch_other) %>%
  filter(spc_common != "null",
           if_all(-spc_common, ~ .x != "null")) %>%
  mutate(across(brch_light:brch_other, ~ ifelse(.x == "Yes", 1, 0)),
           None = ifelse(brch_light == 0 &
                         brch_shoe == 0 &
                         brch_other == 0, 1, 0)) %>%
  group_by(spc_common) %>%
  summarize(none = 100*sum(None)/n(),
              brch_light = 100*sum(brch_light)/n(),
              brch_shoe = 100*sum(brch_shoe)/n(),
              brch_other = 100*sum(brch_other)/n()) %>%
  rename(`Common name of the species` = spc_common,
           `''Lights or wires ` = brch_light,
           `'Shoes` = brch_shoe,
           `Others` = brch_other) %>% 
  ungroup() %>%
  filter(rank((none)) <= 25) %>%
  arrange((none)) %>%
    mutate_if(is.numeric, ~(round(., digits = 2))) %>%
  pivot_longer(cols = c(3:5), 
                 names_to = "Branch problem",
                 values_to = "% of trees")

Fig. 13: Bar Graph of the Top 25 Tree Species with the Highest Percentage of Trees Having Branch Problems

2.2.3. Ranking

As suggested by the urban design team, tree size and health are used to determine which species have the most desirable characteristics. The two metrics used are health index (HI) and median trunk diameter at breast height (DBH) of 54 inches, respectively.

spearman_corr <- data.frame(
    test_stat=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh,
         method = "spearman", exact = FALSE)$statistic,
    corr_coeff=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh,
         method = "spearman", exact = FALSE)$estimate,
    p_value=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh,
         method = "spearman", exact = FALSE)$p.value)

kendall_corr <- data.frame(
    test_stat=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh,
         method = "kendall", exact = FALSE)$statistic,
    corr_coeff=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh,
         method = "kendall", exact = FALSE)$estimate,
    p_value=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh,
         method = "kendall", exact = FALSE)$p.value)

pearson_corr <- data.frame(
    test_stat=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh)$statistic,
    corr_coeff=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh)$estimate,
    p_value=cor.test(spc_health_index$health_index, spc_tree_dbh_stats$median_tree_dbh)$p.value)

corr_coeffs <- spearman_corr %>%
    mutate(method = "Spearman") %>%
  bind_rows(kendall_corr %>%
                mutate(method = "Kendall"), 
              pearson_corr %>%
                mutate(method = "Pearson")) %>%
  select(method, everything()) %>%
  mutate(p_value = formatC(p_value, format = "e", digits = 4))

rownames(corr_coeffs) <- 1:nrow(corr_coeffs)

corr_coeffs %>%
  mutate_if(is.numeric, list(~round(., digits=4))) %>%
  mutate_if(is.numeric, list(~prettyNum(., big.mark=",")))

With that, it is confirmed through a correlation analysis that they have a high to very high positive correlation. This means that an increase in median trunk diameter is associated to an increase in the health index of a species. Below are the results of the correlation tests using three methods:

MethodTest StatisticCorrelation Coefficientp-value
Spearman4,759.5010.98641.2123e-100
Kendall14.78120.93611.9379e-49
Pearson15.46710.80936.6475e-31

To determine species ranking, the sum of ranks for health index and median trunk diameter was computed to quantify each species’ overall rank relative to others.

Additionally, two ranking systems were produced. The first encompassed all 128 species. The second, however, adjusted for abundance by including only species with tree counts of at least 29, representing the median species abundance.

Figures 14 and 15 provide dashboard snapshots illustrating the results from both ranking systems.

# First Ranking System
spc_first_ranking <- spc_health_index %>%
  select(spc_common, abundance, health_index) %>%
  inner_join(trees %>% 
               group_by(spc_common) %>%
               filter(spc_common != "null", health != "null") %>%
               summarize(abundance = n(),
                         median_tree_dbh = median(tree_dbh)),
      by=c("spc_common", "abundance")) %>%
  mutate(abd_rank = rank(desc(abundance)),
       hi_rank = rank(desc(health_index)),
       dbh_rank = rank(desc(median_tree_dbh)),
       rank_sum = (hi_rank + dbh_rank)/2) %>%
  arrange(rank_sum)

# Second Ranking System
spc_second_ranking <- spc_health_index %>%
  select(spc_common, abundance, health_index) %>%
  inner_join(trees %>% 
               group_by(spc_common) %>%
               filter(spc_common != "null", health != "null") %>%
               summarize(abundance = n(),
                         median_tree_dbh = median(tree_dbh)),
      by=c("spc_common", "abundance")) %>%
      
# Filter out species with abundances less than the median abundances
  filter(abundance >= median(spc_tree_dbh_stats$abundance)
          ) %>% 
mutate(abd_rank = rank(desc(abundance)),
       hi_rank = rank(desc(health_index)),
          dbh_rank = rank(desc(median_tree_dbh)),
       rank_sum = (hi_rank + dbh_rank)) %>%
  arrange(rank_sum)

# For graphs
spc_first_ranking_long <- spc_first_ranking %>%
  rename(`Common name of the species` = spc_common,
           `Health index` = health_index,
           `Median trunk dbh` = median_tree_dbh) %>%
  pivot_longer(cols = c(3:4), 
                 names_to = "Measurement",
                 values_to = "Value")

spc_second_ranking_long <- spc_second_ranking %>%
  rename(`Common name of the species` = spc_common,
           `Health index` = health_index,
           `Median trunk dbh` = median_tree_dbh) %>%
  pivot_longer(cols = c(3:4), 
                 names_to = "Measurement",
                 values_to = "Value")

# Tree size and Health 
top_spc_first_ranking <- spc_first_ranking_long %>%
  arrange(rank_sum) %>%
  filter(`Common name of the species` %in% (spc_first_ranking %>% slice(1:10))$spc_common)

top_spc_second_ranking <- spc_second_ranking_long %>%
  arrange(rank_sum) %>%
  filter(`Common name of the species` %in% (spc_second_ranking %>% slice(1:10))$spc_common)


# Tree size
top_dbh_spc <- spc_second_ranking_long %>%
  arrange(desc(Measurement)) %>%
  filter(Measurement == "Median trunk dbh",
           `Common name of the species` %in% (spc_second_ranking %>% slice(1:10))$spc_common)

# Health
top_hi_spc <- spc_second_ranking_long %>%
  arrange(desc(Measurement)) %>%
  rename(`Health index` = Value) %>%
  filter(`Measurement` == "Health index",
           `Common name of the species` %in% (spc_second_ranking %>% slice(1:10))$spc_common) 

Fig. 14: Dashboard Results Using ‘Rank All Species, by Size & Health’ System

Fig. 14: Dashboard Results Using 'Rank All Species, by Size & Health' System

Fig. 15: Dashboard Results Using ‘Rank Species with Abundance ≥ 29, by Size & Health’

Fig. 15: Dashboard Results Using 'Rank Species with Abundance ≥ 29, by Size & Health

3. Recommendations

The following are some potential courses of action for Manhattan’s urban planning department:

  • Large southern neighborhoods such as Midtown-Midtown South (MN17), SoHo–TriBeCa–Civic Center–Little Italy (MN24), and Lower East Side (MN28), which are ranked third, sixth, and eighth in terms of land area, respectively, but only ranked 25th, 15th, and 19th in terms of tree counts, can be ideal locations for planting trees.

  • Some of the issues that need to be prioritized in the Stuyvesant Town-Cooper Village neighborhood include low tree counts, species richness, and a high number of trees that are offset from curb.

  • Although two rankings were produced, the second one has a better rank estimation due to large sample size per species; thus, the top five species (out of the 64 included) in terms of size and health that are recommended to be planted on the streets of Manhattan are:

  1. Siberian elm

    • Abundance: 156
    • Median trunk diameter: 11 (3rd)
    • Heath index: 0.9316 (6th)
  2. Willow oak

    • Abundance: 889
    • Median trunk diameter: 10 (6th)
    • Heath index: 0.9366 (5th)
  3. Honeylocust

    • Abundance: 13,176
    • Median trunk diameter: 9 (12th)
    • Heath index: 0.9387 (4th)
  4. American elm

    • Abundance: 1,698
    • Median trunk diameter: 12 (2nd)
    • Heath index: 0.9185 (17th)
  5. Pin oak

    • Abundance: 4,584
    • Median trunk diameter: 9 (12th)
    • Heath index: 0.9282 (9th)
  • Trees of species Smoketree, Black maple, Amur cork tree, Pitch pine, and Red horse chestnut from the first ranking can also be considered as they have shown superior sizes and health. However, it is also suggested looking into related literature and/or more adequate data about them.

4. Appendix

4.1. Tables & Figures

4.1.1. Shape area per neighborhood

neighborhoods %>%
  filter(boroname == "Manhattan", ntacode != "MN99") %>%
  arrange(desc(shape_area)) %>%
  st_drop_geometry() %>%
  select(-boroname)
ntacodentanameshape_area
1MN13Hudson Yards-Chelsea-Flatiron-Union Square37029727
2MN12Upper West Side34381053
3MN17Midtown-Midtown South30192057
4MN03Central Harlem North-Polo Grounds25403425
5MN23West Village25000526
6MN24SoHo-TriBeCa-Civic Center-Little Italy24859569
7MN34East Harlem North24495420
8MN28Lower East Side23297616
9MN36Washington Heights South23100223
10MN35Washington Heights North22662313
11MN31Lenox Hill-Roosevelt Island21501565
12MN09Morningside Heights20158317
13MN40Upper East Side-Carnegie Hill20065329
14MN25Battery Park City-Lower Manhattan19056256
15MN15Clinton18381380
16MN01Marble Hill-Inwood17725321
17MN19Turtle Bay-East Midtown17397872
18MN33East Harlem South16650738
19MN04Hamilton Heights16093788
20MN14Lincoln Square15805668
21MN27Chinatown14501953
22MN20Murray Hill-Kips Bay14465848
23MN11Central Harlem South14436192
24MN32Yorkville13594780
25MN22East Village10895491
26MN06Manhattanville10647078
27MN21Gramercy 7531455
28MN50Stuyvesant Town-Cooper Village 5575232

4.1.2. Tree count per neighborhood

# Tree count per neighborhood
nbh_tree_cnts %>%
  mutate(Percentage = label_percent(accuracy=0.01)(proportion)) %>%
  select(-proportion)
ntanta_namenumber_of_treesPercentage
MN12Upper West Side58079.04%
MN40Upper East Side-Carnegie Hill46167.19%
MN23West Village38015.92%
MN03Central Harlem North-Polo Grounds34695.40%
MN13Hudson Yards-Chelsea-Flatiron-Union Square29314.56%
MN36Washington Heights South29244.55%
MN09Morningside Heights27044.21%
MN11Central Harlem South26434.11%
MN35Washington Heights North26124.07%
MN34East Harlem North25053.90%
MN04Hamilton Heights23633.68%
MN31Lenox Hill-Roosevelt Island22773.55%
MN19Turtle Bay-East Midtown22263.47%
MN32Yorkville21803.39%
MN24SoHo-TriBeCa-Civic Center-Little Italy21703.38%
MN14Lincoln Square20443.18%
MN15Clinton19543.04%
MN33East Harlem South19453.03%
MN28Lower East Side19162.98%
MN20Murray Hill-Kips Bay17042.65%
MN22East Village15422.40%
MN01Marble Hill-Inwood14762.30%
MN27Chinatown14572.27%
MN25Battery Park City-Lower Manhattan12942.01%
MN17Midtown-Midtown South11841.84%
MN21Gramercy11421.78%
MN06Manhattanville 9021.40%
MN50Stuyvesant Town-Cooper Village 4410.69%

4.1.3. Tree count per curb location

number_of_trees_per_curb_loc
curb_locnumber_of_treespercentage
OnCurb5993293.07%
OffsetFromCurb 42976.67%

4.1.4. Curb location per neighborhood

# Curb location per neighborhood
curb_loc_per_nbh %>%
  arrange(desc(curb_loc), desc(proportion)) %>%
  select(-proportion)
ntanta_namecurb_locnumber_of_treespercentage
MN22East VillageOnCurb153399.42%
MN06ManhattanvilleOnCurb 89098.67%
MN21GramercyOnCurb111997.99%
MN23West VillageOnCurb372197.90%
MN13Hudson Yards-Chelsea-Flatiron-Union SquareOnCurb286097.58%
MN32YorkvilleOnCurb212797.57%
MN15ClintonOnCurb190697.54%
MN35Washington Heights NorthOnCurb252896.78%
MN31Lenox Hill-Roosevelt IslandOnCurb219896.53%
MN34East Harlem NorthOnCurb241096.21%
MN36Washington Heights SouthOnCurb280595.93%
MN03Central Harlem North-Polo GroundsOnCurb332495.82%
MN20Murray Hill-Kips BayOnCurb163095.66%
MN11Central Harlem SouthOnCurb252395.46%
MN01Marble Hill-InwoodOnCurb140895.39%
MN04Hamilton HeightsOnCurb224695.05%
MN19Turtle Bay-East MidtownOnCurb211595.01%
MN17Midtown-Midtown SouthOnCurb110493.24%
MN40Upper East Side-Carnegie HillOnCurb430193.18%
MN14Lincoln SquareOnCurb185190.56%
MN12Upper West SideOnCurb522589.98%
MN24SoHo-TriBeCa-Civic Center-Little ItalyOnCurb195089.86%
MN28Lower East SideOnCurb171489.46%
MN33East Harlem SouthOnCurb172588.69%
MN09Morningside HeightsOnCurb229384.80%
MN27ChinatownOnCurb121883.60%
MN25Battery Park City-Lower ManhattanOnCurb100977.98%
MN50Stuyvesant Town-Cooper VillageOnCurb 19945.12%
MN50Stuyvesant Town-Cooper VillageOffsetFromCurb 24254.88%
MN25Battery Park City-Lower ManhattanOffsetFromCurb 28522.02%
MN27ChinatownOffsetFromCurb 23916.40%
MN09Morningside HeightsOffsetFromCurb 41115.20%
MN33East Harlem SouthOffsetFromCurb 22011.31%
MN28Lower East SideOffsetFromCurb 20210.54%
MN24SoHo-TriBeCa-Civic Center-Little ItalyOffsetFromCurb 22010.14%
MN12Upper West SideOffsetFromCurb 58210.02%
MN14Lincoln SquareOffsetFromCurb 1939.44%
MN40Upper East Side-Carnegie HillOffsetFromCurb 3156.82%
MN17Midtown-Midtown SouthOffsetFromCurb 806.76%
MN19Turtle Bay-East MidtownOffsetFromCurb 1114.99%
MN04Hamilton HeightsOffsetFromCurb 1174.95%
MN01Marble Hill-InwoodOffsetFromCurb 684.61%
MN11Central Harlem SouthOffsetFromCurb 1204.54%
MN20Murray Hill-Kips BayOffsetFromCurb 744.34%
MN03Central Harlem North-Polo GroundsOffsetFromCurb 1454.18%
MN36Washington Heights SouthOffsetFromCurb 1194.07%
MN34East Harlem NorthOffsetFromCurb 953.79%
MN31Lenox Hill-Roosevelt IslandOffsetFromCurb 793.47%
MN35Washington Heights NorthOffsetFromCurb 843.22%
MN15ClintonOffsetFromCurb 482.46%
MN32YorkvilleOffsetFromCurb 532.43%
MN13Hudson Yards-Chelsea-Flatiron-Union SquareOffsetFromCurb 712.42%
MN23West VillageOffsetFromCurb 802.10%
MN21GramercyOffsetFromCurb 232.01%
MN06ManhattanvilleOffsetFromCurb 121.33%
MN22East VillageOffsetFromCurb 90.58%
# Tree population's attributes
pop_attributes %>%
  select(-proportion)
attributecategorynumber_of_treespercentage
statusAlive6242797.19%
statusDead 18022.81%
healthGood4735875.86%
healthFair1146018.36%
healthPoor 36095.78%
root_stoneNo5165380.42%
root_stoneYes1257619.58%
root_grateNo6174796.14%
root_grateYes 24823.86%
root_otherNo5921292.19%
root_otherYes 50177.81%
trunk_wireNo6331298.57%
trunk_wireYes 9171.43%
trnk_lightNo6389899.48%
trnk_lightYes 3310.52%
trnk_otherNo5864991.31%
trnk_otherYes 55808.69%
brch_lightNo6335498.64%
brch_lightYes 8751.36%
brch_shoeNo6416899.91%
brch_shoeYes 610.09%
brch_otherNo5766589.78%
brch_otherYes 656410.22%

4.1.3. Richness (number of tree species) per neighborhood

nbh_rchns
ntanta_namerichness
MN35Washington Heights North81
MN28Lower East Side78
MN36Washington Heights South77
MN23West Village76
MN03Central Harlem North-Polo Grounds75
MN04Hamilton Heights73
MN12Upper West Side73
MN40Upper East Side-Carnegie Hill73
MN11Central Harlem South71
MN22East Village68
MN09Morningside Heights66
MN34East Harlem North64
MN24SoHo-TriBeCa-Civic Center-Little Italy62
MN01Marble Hill-Inwood60
MN19Turtle Bay-East Midtown60
MN27Chinatown58
MN32Yorkville57
MN31Lenox Hill-Roosevelt Island55
MN14Lincoln Square54
MN20Murray Hill-Kips Bay53
MN06Manhattanville52
MN15Clinton52
MN33East Harlem South46
MN13Hudson Yards-Chelsea-Flatiron-Union Square44
MN21Gramercy39
MN25Battery Park City-Lower Manhattan39
MN17Midtown-Midtown South37
MN50Stuyvesant Town-Cooper Village21

4.1.6. Summary statistics of species abundances (number of trees per species)

defaultW <- getOption("warn")
options(warn=-1)

tree_attributes <- trees %>%
  select(spc_common, tree_dbh:brch_other) %>%
  filter(!is.na(spc_common))

spc_common <- levels(factor(tree_attributes$spc_common))

tree_attributes$spc_common <- factor(tree_attributes$spc_common,
                               levels = spc_common)

# Identified species abundances
identified_spc_abd <- trees %>%
  filter(!is.na(spc_common)) %>%
  group_by(spc_common) %>%
  summarize(abundance = n())

# Summary statistics of species abundances
spc_abd_stats <- data.frame(number_of_identified_spc = length(identified_spc_abd$abundance),
                mean = mean(identified_spc_abd$abundance),
                            sd = sd(identified_spc_abd$abundance),
                            min = min(identified_spc_abd$abundance),
                            first_quartile = quantile(identified_spc_abd$abundance, probs = 0.25),
                            median = median(identified_spc_abd$abundance),
                            third_quartile = quantile(identified_spc_abd$abundance, probs = 0.75),
                            max = max(identified_spc_abd$abundance))
row.names(spc_abd_stats) <- "spc_abundance" 

# HTML Table for Number of Trees per Species
#kable(tree_dbh_stats %>%
#	  	mutate_if(is.numeric, list(~format(round(., 4), nsmall = 4))),
#     "html", caption = "Table _: Summary statistics of the tree diameter")

# Histogram with density curve of the species abundances
tree_count_per_species_dist_plot <- ggplot(identified_spc_abd,
                                           aes(x = abundance)) + 
  geom_histogram(aes(y = after_stat(density)),
                   binwidth=25,
                   color=1,
                   fill="#5FBD5F") + geom_density(linewidth=0.85,
                                                  linetype=1,
                                                  colour = muted("5FBD5F"),
                                                  alpha=0.5) +

# Plot mean and median
  geom_vline(aes(xintercept = mean(abundance)), col="red", size=0.6) +
  geom_vline(aes(xintercept = median(abundance)), col="blue", size=0.6) +

  theme(axis.title = element_text(color="#65707C",
                                    face="bold",
                                    family="sans serif"),
          axis.text = element_text(color="#65707C",
                                   size=12,
                                   family="sans serif"),
          axis.line = element_line(colour="grey",
                                   linewidth=0.5),
          panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.25),
          panel.background = element_blank(),
          plot.subtitle = element_text(color="#65707C",
                                    hjust=-0.33,
                                    size=10,
                                    family="sans serif"),
          plot.title = element_text(color="#65707C",
                                    hjust=0.5,
                                    size=14,
                                    family="sans serif")) +
  ggtitle("\nFig. 16: Distribution of the Species Abundance                \n") +
  labs(x="\nSpecies abundance\n", y="\nDensity\n") +
  scale_x_continuous(expand = c(0.01, 0), 
                       limits = c(0, 2550),
                       breaks = seq(0, 2550, by=250)) +
  scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0, 0.0081), 
                       breaks = seq(0, 0.0081, by=0.001))

spc_abd_stats

options(warn = defaultW)
number_of_identified_spcmeansdminfirst_quartilemedianthird_quartilemax
spc_abundance128487.71881597.82818.7528.5167.7513176

4.1.7. Summary statistics of species’ tree DBHs

# Summary statistics of species' tree dbhs
spc_tree_dbh_stats
spc_commonabundancemean_tree_dbhsd_tree_dbhmin_tree_dbhfirst_quartile_tree_dbhmedian_tree_dbhthird_quartile_tree_dbhmax_tree_dbh
Weeping willow 1213.5000007.317476 4 8.0014.019.00 26
London planetree 412213.1686077.340801 1 7.0013.018.00 48
White pine 113.000000 NA1313.0013.013.00 13
American elm 169813.8992939.703312 1 6.0012.019.00 62
Amur cork tree 8 9.6250003.925648 3 8.5011.012.25 13
Black maple 1012.6000008.408990 4 5.0011.019.50 26
Ohio buckeye 2411.9583335.368824 3 9.5011.015.25 24
Siberian elm 15612.0641037.545714 2 5.7511.017.00 33
Smoketree 111.000000 NA1111.0011.011.00 11
Sycamore maple 2311.5217396.280341 2 7.5011.016.00 26
Tree of heaven 10411.4519236.584595 2 5.0011.016.00 34
Ash 58 9.6034482.943561 3 8.0010.011.75 16
Black locust 259 9.7683404.735689 2 5.0010.013.00 21
Willow oak 88910.8110249.331016 1 5.0010.014.00199
White ash 50 9.8000004.347178 3 6.00 9.513.00 18
Black walnut 33 9.6363646.004260 2 4.00 9.013.00 26
Eastern cottonwood 1010.8000006.178817 3 7.25 9.011.75 22
Green ash 770 9.2558444.371351 0 6.00 9.012.00 28
Honeylocust13176 9.0580603.997006 0 6.00 9.011.00109
Mulberry 6811.0000007.732467 1 5.00 9.015.00 44
Norway maple 29010.2379315.801379 2 6.00 9.013.00 35
Pin oak 458410.0684997.982340 1 5.00 9.013.00318
Sophora 4453 9.2259154.892435 1 5.00 9.013.00 38
Callery pear 7297 8.6813764.717342 1 6.00 8.011.00228
Catalpa 13 8.5384624.370648 4 6.00 8.0 9.00 21
Ginkgo 5859 8.4459814.159496 1 5.00 8.011.00 74
Pignut hickory 1 8.000000 NA 8 8.00 8.0 8.00 8
Pitch pine 5 7.4000003.286335 4 4.00 8.010.00 11
Red horse chestnut 1 8.000000 NA 8 8.00 8.0 8.00 8
American hophornbeam 84 8.3452384.956422 2 4.00 7.512.00 22
Shingle oak2055.8536594.278084713.004.0 7.0030
Southern red oak 77.1428574.488079434.004.010.5014
Sweetgum2274.9911893.376114923.004.0 6.0022
Tulip-poplar 344.2352940.955330324.004.0 5.00 6
Turkish hazelnut 174.7647062.905370323.004.0 5.0011
White oak2415.2406642.906918123.004.0 7.0017
American beech 225.2272733.841277313.003.5 7.5016
Blackgum 93.5555562.554951622.003.0 4.0010
Chinese fringetree 93.5555561.666666722.003.0 4.00 7
Common hackberry1704.3235292.848445912.003.0 5.0014
Eastern hemlock 73.5714290.786795833.003.0 4.00 5
Eastern redcedar 423.4761902.109653722.003.0 4.0010
Hardy rubber tree 663.8030302.275080422.003.0 5.0014
Horse chestnut 113.0909090.700649023.003.0 3.50 4
Kentucky yellowwood 184.6666673.235828823.003.0 4.0014
Mimosa 123.7500002.598076212.003.0 4.2511
Norway spruce 34.0000002.645751322.503.0 5.00 7
Pagoda dogwood 184.8888894.444281022.253.0 4.0016
Paperbark maple 153.2666671.709915112.003.0 4.00 8
Sassafras 175.4705884.229622423.003.0 6.0016
Spruce 13.000000 NA33.003.0 3.00 3
Swamp white oak6814.0279002.472338103.003.0 4.0032
Blue spruce 44.2500003.862210122.002.5 4.7510
Pond cypress 122.6666670.887625422.002.5 3.00 5
Scots pine 22.5000000.707106822.252.5 2.75 3
Arborvitae 53.4000003.130495222.002.0 2.00 9
Douglas-fir 22.0000001.414213611.502.0 2.50 3
Himalayan cedar 62.3333330.516397822.002.0 2.75 3
Persian ironwood 12.000000 NA22.002.0 2.00 2
Osage-orange 10.000000 NA00.000.0 0.00 0

4.1.8. Status per species

# Status per species
spc_status
spc_commonstatusnumber_of_treespercentage_wrt_spc
HoneylocustDead 10.01%
HoneylocustAlive1317599.99%
'Schubert' chokecherryAlive 163100.00%
American beechAlive 22100.00%
American elmAlive 1698100.00%
American hophornbeamAlive 84100.00%
American hornbeamAlive 85100.00%
American larchAlive 7100.00%
American lindenAlive 1583100.00%
Amur cork treeAlive 8100.00%
Amur maackiaAlive 59100.00%
Amur mapleAlive 30100.00%
ArborvitaeAlive 5100.00%
AshAlive 58100.00%
Atlantic white cedarAlive 12100.00%
Bald cypressAlive 89100.00%
Bigtooth aspenAlive 5100.00%
Black cherryAlive 32100.00%
Black locustAlive 259100.00%
Black mapleAlive 10100.00%
Black oakAlive 192100.00%
Black pineAlive 3100.00%
Black walnutAlive 33100.00%
BlackgumAlive 9100.00%
Blue spruceAlive 4100.00%
BoxelderAlive 2100.00%
Bur oakAlive 36100.00%
Callery pearAlive 7297100.00%
CatalpaAlive 13100.00%
CherryAlive 869100.00%
Sawtooth oakAlive 353100.00%
Scarlet oakAlive 71100.00%
Schumard's oakAlive 137100.00%
Scots pineAlive 2100.00%
ServiceberryAlive 38100.00%
Shingle oakAlive 205100.00%
Siberian elmAlive 156100.00%
Silver birchAlive 10100.00%
Silver lindenAlive 541100.00%
Silver mapleAlive 71100.00%
SmoketreeAlive 1100.00%
SophoraAlive4453100.00%
Southern magnoliaAlive 19100.00%
Southern red oakAlive 7100.00%
SpruceAlive 1100.00%
Sugar mapleAlive 48100.00%
Swamp white oakAlive 681100.00%
SweetgumAlive 227100.00%
Sycamore mapleAlive 23100.00%
Tartar mapleAlive 12100.00%
Tree of heavenAlive 104100.00%
Tulip-poplarAlive 34100.00%
Turkish hazelnutAlive 17100.00%
Two-winged silverbellAlive 8100.00%
Virginia pineAlive 3100.00%
Weeping willowAlive 12100.00%
White ashAlive 50100.00%
White oakAlive 241100.00%
White pineAlive 1100.00%
Willow oakAlive 889100.00%

4.1.9. Health per species

# Health per species
spc_health %>%
  select(-proportion)
spc_commonhealthnumber_of_treespercentage
'Schubert' chokecherryGood 11168.10%
'Schubert' chokecherryFair 4024.54%
'Schubert' chokecherryPoor 127.36%
American beechGood 1568.18%
American beechFair 418.18%
American beechPoor 313.64%
American elmGood136180.15%
American elmFair 25915.25%
American elmPoor 784.59%
American hophornbeamGood 6476.19%
American hophornbeamFair 1214.29%
American hophornbeamPoor 89.52%
American hornbeamGood 6778.82%
American hornbeamFair 1315.29%
American hornbeamPoor 55.88%
American larchFair 342.86%
American larchGood 342.86%
American larchPoor 114.29%
American lindenGood102064.43%
American lindenFair 37923.94%
American lindenPoor 18411.62%
Amur cork treeGood 787.50%
Amur cork treeFair 112.50%
Amur maackiaGood 4677.97%
Amur maackiaFair 1016.95%
Amur maackiaPoor 35.08%
Amur mapleGood 1963.33%
Amur mapleFair 723.33%
Amur maplePoor 413.33%
ArborvitaeGood 5100.00%
Sycamore mapleFair 730.43%
Sycamore maplePoor 28.70%
Tartar mapleGood 541.67%
Tartar mapleFair 433.33%
Tartar maplePoor 325.00%
Tree of heavenGood 8278.85%
Tree of heavenFair 1716.35%
Tree of heavenPoor 54.81%
Tulip-poplarGood 1750.00%
Tulip-poplarFair 1029.41%
Tulip-poplarPoor 720.59%
Turkish hazelnutFair 952.94%
Turkish hazelnutGood 741.18%
Turkish hazelnutPoor 15.88%
Two-winged silverbellGood 562.50%
Two-winged silverbellFair 337.50%
Virginia pineGood 266.67%
Virginia pinePoor 133.33%
Weeping willowGood 866.67%
Weeping willowFair 433.33%
White ashGood 4080.00%
White ashFair 816.00%
White ashPoor 24.00%
White oakGood16267.22%
White oakFair 5623.24%
White oakPoor 239.54%
White pineFair 1100.00%
Willow oakGood74784.03%
Willow oakFair11512.94%
Willow oakPoor 273.04%

4.1.10. Health index per species

spc_health_index %>%
  select(-abundance)
spc_commonhealth_index
Arborvitae1.0000000
Black pine1.0000000
Blue spruce1.0000000
Crepe myrtle1.0000000
European beech1.0000000
Osage-orange1.0000000
Persian ironwood1.0000000
Pitch pine1.0000000
Red horse chestnut1.0000000
Red pine1.0000000
Scots pine1.0000000
Smoketree1.0000000
Black maple0.9666667
Amur cork tree0.9583333
Golden raintree0.9554318
Southern red oak0.9523810
Sawtooth oak0.9471199
Kentucky coffeetree0.9415709
Japanese maple0.9393939
Honeylocust0.9387223
Willow oak0.9366329
Holly0.9358974
Siberian elm0.9316239
Southern magnolia0.9298246
Eastern redcedar0.9285714
Hawthorn0.9284627
Pin oak0.9282286
Crab apple0.9260107
Blackgum0.9259259
Shingle oak0.9252033
Bigtooth aspen0.8000000
Eastern cottonwood0.8000000
Japanese snowbell0.8000000
Hedge maple0.7971014
Sassafras0.7843137
Turkish hazelnut0.7843137
Silver maple0.7840376
Katsura tree0.7807018
Cucumber magnolia0.7777778
Kentucky yellowwood0.7777778
Norway spruce0.7777778
Pine0.7777778
Virginia pine0.7777778
Tulip-poplar0.7647059
American larch0.7619048
Horse chestnut0.7575758
Pagoda dogwood0.7407407
Tartar maple0.7222222
Maple0.7027027
Cockspur hawthorn0.6666667
Douglas-fir0.6666667
Paperbark maple0.6666667
Pignut hickory0.6666667
Spruce0.6666667
White pine0.6666667
Crimson king maple0.5555556
Pond cypress0.5555556
Eastern hemlock0.5238095
Boxelder0.5000000
European alder0.5000000

4.1.11. Species’ distribution of root problems

trees %>%
  select(spc_common, root_stone:root_other) %>%
  filter(spc_common != "null",
           if_all(-spc_common, ~ .x != "null")) %>%
  mutate(across(root_stone:root_other, ~ ifelse(.x == "Yes", 1, 0)),
           no_problem = ifelse(root_stone == 0 &
                               root_grate == 0 &
                               root_other == 0, 1, 0)) %>%
  group_by(spc_common) %>%
  summarize(no_problem = 100*sum(no_problem)/n(),
              root_stone = 100*sum(root_stone)/n(),
              root_grate = 100*sum(root_grate)/n(),
              root_other = 100*sum(root_other)/n()) %>%
  arrange(no_problem) %>%
    mutate_if(is.numeric, ~(round(., digits = 2)))
spc_commonno_problemroot_stoneroot_grateroot_other
White pine 0.00100.00 0.00 0.00
European beech16.67 50.00 0.0050.00
Tartar maple16.67 66.67 0.0016.67
Southern magnolia26.32 57.89 0.0021.05
Norway spruce33.33 0.00 0.0066.67
Katsura tree42.11 28.9521.05 7.89
Tree of heaven45.19 43.27 1.9212.50
Sassafras47.06 35.29 0.0023.53
Boxelder50.00 50.00 0.00 0.00
Cucumber magnolia50.00 16.6733.3333.33
European alder50.00 50.00 0.00 0.00
Quaking aspen50.00 50.00 0.00 0.00
Weeping willow50.00 33.33 0.0016.67
Ohio buckeye58.33 29.17 0.0012.50
Empress tree58.82 41.18 0.00 0.00
Cornelian cherry59.26 3.7033.33 3.70
Crepe myrtle60.00 40.00 0.00 0.00
Eastern cottonwood60.00 30.00 0.0020.00
Black walnut60.61 39.39 3.03 0.00
Japanese tree lilac62.02 22.48 8.5310.85
Honeylocust62.15 25.50 6.2810.66
Japanese hornbeam64.52 25.81 3.23 9.68
Green ash65.45 26.88 1.04 8.83
Cockspur hawthorn66.67 33.33 0.0033.33
Crimson king maple66.67 33.33 0.0016.67
Oklahoma redbud66.67 33.33 0.00 0.00
Paperbark maple66.67 13.33 6.6720.00
Virginia pine66.67 33.33 0.00 0.00
Norway maple67.24 27.93 1.03 7.93
Callery pear67.60 20.87 7.02 8.17
Eastern redbud 92.004.0004.00
River birch 92.593.7003.70
Magnolia 93.105.1701.72
Bur oak 94.442.7802.78
American hornbeam 95.293.5301.18
Crab apple 96.342.7501.14
Eastern redcedar 97.620.0002.38
Hawthorn 97.720.9101.37
European hornbeam 98.200.0001.80
American larch100.000.0000.00
Arborvitae100.000.0000.00
Bigtooth aspen100.000.0000.00
Black pine100.000.0000.00
Blue spruce100.000.0000.00
Douglas-fir100.000.0000.00
Himalayan cedar100.000.0000.00
Kousa dogwood100.000.0000.00
Osage-orange100.000.0000.00
Persian ironwood100.000.0000.00
Pignut hickory100.000.0000.00
Pine100.000.0000.00
Pitch pine100.000.0000.00
Pond cypress100.000.0000.00
Red horse chestnut100.000.0000.00
Red pine100.000.0000.00
Scots pine100.000.0000.00
Smoketree100.000.0000.00
Southern red oak100.000.0000.00
Spruce100.000.0000.00
Two-winged silverbell100.000.0000.00

4.1.12. Species’ distribution of trunk problems

trees %>%
  select(spc_common, trunk_wire:trnk_other) %>%
  filter(spc_common != "null",
           if_all(-spc_common, ~ .x != "null")) %>%
  mutate(across(trunk_wire:trnk_other, ~ ifelse(.x == "Yes", 1, 0)),
           no_problem = ifelse(trunk_wire == 0 &
                               trnk_light == 0 &
                               trnk_other == 0, 1, 0)) %>%
  group_by(spc_common) %>%
  summarize(no_problem = 100*sum(no_problem)/n(),
              trunk_wire = 100*sum(trunk_wire)/n(),
              trnk_light = 100*sum(trnk_light)/n(),
              trnk_other = 100*sum(trnk_other)/n()) %>%
  arrange(no_problem) %>%
    mutate_if(is.numeric, ~(round(., digits = 2)))
spc_commonno_problemtrunk_wiretrnk_lighttrnk_other
Tartar maple41.67 0.00 0.0058.33
Oklahoma redbud44.4411.11 0.0044.44
Horse chestnut63.6418.18 0.0018.18
Cockspur hawthorn66.6733.33 0.00 0.00
Crimson king maple66.67 0.00 0.0033.33
Paperbark maple66.67 0.00 0.0033.33
Hedge maple69.57 4.35 0.0026.09
Japanese snowbell73.33 0.00 0.0026.67
Pond cypress75.00 0.00 0.0025.00
Silver maple77.46 8.45 0.0014.08
Ohio buckeye79.17 0.00 0.0020.83
Eastern cottonwood80.00 0.00 0.0020.00
Pitch pine80.00 0.00 0.0020.00
Silver birch80.0010.0010.0010.00
Maple81.08 0.0010.81 8.11
Tulip-poplar82.35 0.00 0.0017.65
Paper birch82.98 2.13 0.0014.89
European beech83.33 0.00 0.0016.67
Mimosa83.3316.67 0.00 0.00
Green ash84.16 3.77 0.3912.21
Dawn redwood84.92 2.01 0.0013.57
Japanese hornbeam85.48 4.84 1.61 8.06
Eastern hemlock85.71 0.00 0.0014.29
Southern red oak85.71 0.00 0.0014.29
Sweetgum86.78 2.64 0.4410.13
Sophora87.22 1.46 0.4911.34
Chinese tree lilac87.50 0.00 0.0012.50
London planetree87.70 0.68 0.1511.69
Black walnut87.88 0.00 0.0012.12
Ginkgo87.92 1.69 0.5510.17
Blue spruce100000
Boxelder100000
Catalpa100000
Chinese fringetree100000
Crepe myrtle100000
Cucumber magnolia100000
Douglas-fir100000
Eastern redcedar100000
European alder100000
Himalayan cedar100000
Holly100000
Japanese maple100000
Kousa dogwood100000
Norway spruce100000
Osage-orange100000
Persian ironwood100000
Pignut hickory100000
Pine100000
Quaking aspen100000
Red horse chestnut100000
Red pine100000
Scots pine100000
Smoketree100000
Southern magnolia100000
Spruce100000
Sycamore maple100000
Turkish hazelnut100000
Two-winged silverbell100000
Virginia pine100000
White pine100000

4.1.13. Species’ distribution of branch problems

trees %>%
  select(spc_common, brch_light:brch_other) %>%
  filter(spc_common != "null",
           if_all(-spc_common, ~ .x != "null")) %>%
  mutate(across(brch_light:brch_other, ~ ifelse(.x == "Yes", 1, 0)),
           no_problem = ifelse(brch_light == 0 &
                               brch_shoe == 0 &
                               brch_other == 0, 1, 0)) %>%
  group_by(spc_common) %>%
  summarize(no_problem = 100*sum(no_problem)/n(),
              brch_light = 100*sum(brch_light)/n(),
              brch_shoe = 100*sum(brch_shoe)/n(),
              brch_other = 100*sum(brch_other)/n()) %>%
  arrange(no_problem) %>%
    mutate_if(is.numeric, ~(round(., digits = 2)))
spc_commonno_problembrch_lightbrch_shoebrch_other
Boxelder50.00 0.000.0050.00
Crimson king maple50.00 0.000.0050.00
European alder50.00 0.000.0050.00
Tartar maple50.00 8.330.0050.00
Maple67.5710.810.0021.62
Southern magnolia68.42 0.000.0031.58
Sassafras70.59 5.880.0029.41
Turkish hazelnut70.59 0.000.0029.41
American beech72.73 4.550.0022.73
Paperbark maple73.33 0.000.0026.67
Silver maple74.65 0.000.0025.35
Ohio buckeye75.00 0.000.0025.00
Kentucky yellowwood77.78 0.000.0022.22
Oklahoma redbud77.78 0.000.0022.22
Pagoda dogwood77.78 0.000.0022.22
Arborvitae80.00 0.000.0020.00
Crepe myrtle80.00 0.000.0020.00
Eastern cottonwood80.00 0.000.0020.00
Silver birch80.0020.000.00 0.00
Sugar maple81.25 2.080.0016.67
Cornelian cherry81.48 3.700.0014.81
Horse chestnut81.82 0.000.0018.18
Amur maple83.33 0.000.0016.67
European beech83.33 0.000.0016.67
Callery pear83.92 2.320.1114.13
Paper birch85.11 2.130.0012.77
Honeylocust85.21 2.180.1412.83
Tulip-poplar85.29 0.000.0014.71
Japanese snowbell86.67 0.000.0013.33
Katsura tree86.84 0.000.0013.16
Bigtooth aspen100000
Black maple100000
Black pine100000
Blackgum100000
Blue spruce100000
Chinese tree lilac100000
Cockspur hawthorn100000
Douglas-fir100000
Eastern hemlock100000
Himalayan cedar100000
Kousa dogwood100000
Norway spruce100000
Osage-orange100000
Persian ironwood100000
Pignut hickory100000
Pine100000
Pitch pine100000
Pond cypress100000
Quaking aspen100000
Red horse chestnut100000
Red pine100000
River birch100000
Scots pine100000
Serviceberry100000
Smoketree100000
Southern red oak100000
Spruce100000
Two-winged silverbell100000
Virginia pine100000
White pine100000

4.1.14. Ranking of all 128 tree species

spc_first_ranking %>%
  select(-abd_rank)
spc_commonabundancehealth_indexmedian_tree_dbhhi_rankdbh_rankrank_sum
Smoketree 11.000000011.0 6.5 8.0 7.25
Black maple 100.966666711.013.0 8.010.50
Amur cork tree 80.958333311.014.0 8.011.00
Siberian elm 1560.931623911.023.0 8.015.50
Pitch pine 51.0000000 8.0 6.526.516.50
Red horse chestnut 11.0000000 8.0 6.526.516.50
Willow oak 8890.936632910.021.013.017.00
Honeylocust131750.9387223 9.020.019.519.75
American elm 16980.918531612.036.0 4.020.00
Pin oak 45840.9282286 9.027.019.523.25
Tree of heaven 1040.913461511.039.0 8.023.50
White ash 500.9200000 9.533.015.024.00
Black locust 2590.917631910.037.013.025.00
Black walnut 330.9191919 9.034.019.526.75
Sophora 44530.9187813 9.035.019.527.25
Ohio buckeye 240.902777811.047.0 8.027.50
Japanese maple 110.9393939 6.019.040.029.50
Crepe myrtle 51.0000000 5.0 6.555.030.75
Red pine 11.0000000 5.0 6.555.030.75
Weeping willow 120.888888914.062.0 1.031.50
Golden raintree 3590.9554318 5.015.055.035.00
Schumard's oak 1370.9221411 6.031.040.035.50
Sawtooth oak 3530.9471199 5.017.055.036.00
Green ash 7700.8961039 9.053.019.536.25
European beech 61.0000000 4.5 6.567.036.75
Southern magnolia 190.9298246 5.024.055.039.50
Callery pear 72970.8923759 8.056.026.541.25
Crab apple 4370.9260107 5.028.055.041.50
London planetree 41220.845867713.081.0 2.541.75
Chinese elm 7850.9053079 6.044.040.042.00
Flowering dogwood 650.84102564.0 83.0 87.0 85.00
European alder 20.50000005.5127.5 45.0 86.25
Red maple3560.83895134.0 86.0 87.0 86.50
Chinese fringetree 90.88888893.0 62.0113.0 87.50
Mimosa 120.88888893.0 62.0113.0 87.50
Cockspur hawthorn 30.66666675.0120.5 55.0 87.75
Cucumber magnolia 120.77777784.5109.0 67.0 88.00
Amur maple 300.83333334.0 90.0 87.0 88.50
Bald cypress 890.82771544.0 94.0 87.0 90.50
Boxelder 20.50000005.0127.5 55.0 91.25
Dawn redwood1990.81574544.0 96.0 87.0 91.50
Empress tree 170.80392164.0 97.0 87.0 92.00
American beech 220.84848483.5 80.0105.0 92.50
Hardy rubber tree 660.86363643.0 74.0113.0 93.50
Japanese snowbell 150.80000004.0100.0 87.0 93.50
Turkish hazelnut 170.78431374.0103.5 87.0 95.25
Tulip-poplar 340.76470594.0112.0 87.0 99.50
Common hackberry1700.83529413.0 87.0113.0100.00
Maple 370.70270274.0117.0 87.0102.00
Himalayan cedar 60.83333332.0 90.0125.5107.75
Sassafras 170.78431373.0103.5113.0108.25
Kentucky yellowwood 180.77777783.0109.0113.0111.00
Norway spruce 30.77777783.0109.0113.0111.00
Horse chestnut 110.75757583.0114.0113.0113.50
Pagoda dogwood 180.74074073.0115.0113.0114.00
Paperbark maple 150.66666673.0120.5113.0116.75
Spruce 10.66666673.0120.5113.0116.75
Eastern hemlock 70.52380953.0126.0113.0119.50
Douglas-fir 20.66666672.0120.5125.5123.00
Pond cypress 120.55555562.5124.5122.0123.25

4.1.15. Ranking of all tree species with at least 29 abundances

spc_second_ranking %>%
  select(-abd_rank)
spc_commonabundancehealth_indexmedian_tree_dbhhi_rankdbh_rankrank_sum
Siberian elm 1560.931623911.0 6 3.5 9.5
Willow oak 8890.936632910.0 5 6.011.0
Honeylocust131750.9387223 9.0 412.016.0
American elm 16980.918531612.017 2.019.0
Pin oak 45840.9282286 9.0 912.021.0
White ash 500.9200000 9.514 8.022.0
Tree of heaven 1040.913461511.019 3.522.5
Black locust 2590.917631910.018 6.024.0
Black walnut 330.9191919 9.01512.027.0
Sophora 44530.9187813 9.01612.028.0
Golden raintree 3590.9554318 5.0 130.031.0
Sawtooth oak 3530.9471199 5.0 230.032.0
Schumard's oak 1370.9221411 6.01222.534.5
Crab apple 4370.9260107 5.01030.040.0
Green ash 7700.8961039 9.03112.043.0
Chinese elm 7850.9053079 6.02422.546.5
Japanese zelkova 35960.9048016 6.02622.548.5
Kentucky coffeetree 3480.9415709 4.0 347.550.5
Callery pear 72970.8923759 8.03416.550.5
Ash 580.867816110.045 6.051.0
London planetree 41220.845867713.050 1.051.0
Mulberry 680.8774510 9.04112.053.0
Cherry 8690.9048715 5.02530.055.0
Hawthorn 2190.9284627 4.0 847.555.5
Ginkgo 58590.8882631 8.03916.555.5
American hophornbeam 840.8888889 7.53818.056.0
Magnolia 1160.9022989 5.02730.057.0
Shingle oak 2050.9252033 4.01147.558.5
Japanese hornbeam 620.8924731 5.03330.063.0
Silver linden 5410.8761553 6.04222.564.5
Amur maackia 590.909604542247.5 69.5
Bur oak 360.907407442347.5 70.5
Norway maple 2900.801149496012.0 72.0
American linden15830.842703765122.5 73.5
Swamp white oak 6810.920704831362.5 75.5
Black oak 1920.901041742847.5 75.5
Littleleaf linden33330.828182875719.0 76.0
Eastern redbud 500.900000042947.5 76.5
Scarlet oak 710.896713643047.5 77.5
Black cherry 320.895833343247.5 79.5
Purple-leaf plum 1100.890909143547.5 82.5
Sugar maple 480.840277855330.0 83.0
European hornbeam 1670.890219643647.5 83.5
Katsura tree 380.780701866222.5 84.5
Serviceberry 380.885964944047.5 87.5
Japanese tree lilac 1290.870801044347.5 90.5
Silver maple 710.784037656130.0 91.0
'Schubert' chokecherry 1630.869120744447.5 91.5
White oak 2410.858921244747.5 94.5
Paper birch 470.858156044847.5 95.5
Sweetgum 2270.850220344947.5 96.5
Flowering dogwood 650.841025645247.5 99.5
Red maple 3560.838951345447.5101.5
Amur maple 300.833333345647.5103.5
Bald cypress 890.827715445847.5105.5
Dawn redwood 1990.815745445947.5106.5
Hardy rubber tree 660.863636434662.5108.5
Tulip-poplar 340.764705946347.5110.5
Maple 370.702702746447.5111.5
Common hackberry 1700.835294135562.5117.5