feat: add narratives and clarify visuals in Participant Analysis section.

This commit is contained in:
Nick Heppler 2025-05-07 11:44:58 -04:00
parent 507cb05265
commit 4042c36fff

View File

@ -347,13 +347,48 @@ The following provides additional context for each survey question/field, detail
[Back to Top](#)
## Participant Type
The following section contains an analysis of tree planting by participant type.
## Submissions
### Submissions
The following plot shows the distribution of survey submissions based on participant type. This breakdown highlights the contributions of each participant group to the tree planting initiative.
This chart displays the number of survey submissions by participant type, such as community organizations, municipalities, private landowners, and professionals. It provides insight into who is most actively reporting tree planting activities. Identifying the most engaged participant groups helps DEC tailor outreach and support efforts accordingly.
```{r create-histogram-participant-type, echo=TRUE, message=FALSE, fig.height=6, fig.width=8}
create_histogram <- function(data, field, x_labels = NULL, color_palette = c("#154973", "#457aa5", "#eff6fb", "#face00"),
title = NULL, x_title = NULL, y_title = "Count",
max_label_count = 10, label_angle = 45, show_labels = TRUE) {
primary_color <- color_palette[1]
secondary_color <- color_palette[2]
tertiary_color <- color_palette[3]
accent_color <- color_palette[4]
if (is.null(title)) title <- paste("Distribution of", field)
if (is.null(x_title)) x_title <- field
ggplot(data, aes(x = .data[[field]])) +
geom_bar(fill = primary_color, color = secondary_color, stat = "count") +
(if (show_labels) geom_label(stat = "count", aes(label = scales::comma(after_stat(count))),
position = position_stack(vjust = 0.5),
color = accent_color, size = 5,
fill = primary_color, label.padding = unit(0.25, "lines")) else NULL) +
labs(title = title, x = x_title, y = y_title) +
(if (!is.null(x_labels)) scale_x_discrete(labels = x_labels) else NULL) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(size = 16, face = "bold", color = primary_color),
axis.title = element_text(size = 12, color = primary_color),
axis.text = element_text(size = 10, color = primary_color, angle = label_angle, hjust = 1),
plot.margin = margin(10, 10, 10, 10),
panel.grid.major = element_line(color = tertiary_color, linewidth = 0.2),
panel.grid.minor = element_line(color = tertiary_color, linewidth = 0.1),
panel.background = element_rect(fill = tertiary_color),
axis.text.x = element_text(angle = label_angle, hjust = 1),
axis.text.y = element_text(size = 10, color = primary_color)
)
}
create_histogram(
survey_data,
field = "Who Planted The Tree(s)? (Required)",
@ -369,26 +404,22 @@ create_histogram(
color_palette = c("#233f2b", "#7e9084", "#d9e1dd", "#face00"))
```
## Trees Planted
### Trees Planted
This plot visualizes the total number of trees planted by each participant type, helping to evaluate the overall impact of different groups in the tree planting program.
This chart summarizes the total number of trees planted by each participant type. While some groups may submit more frequently, this view helps highlight the actual planting impact. For example, a smaller number of submissions from professional landscapers might correspond to a large number of trees planted. This supports prioritizing high-impact contributors.
```{r func-create_bar_chart, echo=TRUE, message=FALSE}
```{r create-bar-chart-participant-trees, echo=TRUE, message=FALSE}
create_bar_chart <- function(data, field, sum_field = NULL, x_labels = NULL, color_palette = c("#154973", "#457aa5", "#eff6fb", "#face00"),
title = NULL, x_title = NULL, y_title = "Sum",
max_label_count = 10, label_angle = 45, show_labels = TRUE) {
# Default color palette
primary_color <- color_palette[1]
secondary_color <- color_palette[2]
tertiary_color <- color_palette[3]
accent_color <- color_palette[4]
# Set default labels if not provided
if (is.null(title)) title <- paste("Sum of", field)
if (is.null(x_title)) x_title <- field
# If no sum_field is provided, use counts as the default bar height
if (is.null(sum_field)) {
sum_field <- field
data <- data.frame(!!field := data[[field]], Count = 1)
@ -399,20 +430,13 @@ create_bar_chart <- function(data, field, sum_field = NULL, x_labels = NULL, col
ungroup()
}
# Plot
ggplot(data, aes(x = .data[[field]], y = .data$Sum)) +
geom_bar(stat = "identity", fill = primary_color, color = secondary_color) +
# Add text labels with background and border
(if (show_labels) geom_label(aes(label = scales::comma(Sum)),
position = position_stack(vjust = 0.5),
color = accent_color, size = 5,
fill = primary_color, label.padding = unit(0.25, "lines")) else NULL) +
labs(
title = title,
x = x_title,
y = y_title
) +
# Customize x-axis labels
labs(title = title, x = x_title, y = y_title) +
(if (!is.null(x_labels)) scale_x_discrete(labels = x_labels) else NULL) +
theme_minimal(base_size = 14) +
theme(
@ -427,12 +451,11 @@ create_bar_chart <- function(data, field, sum_field = NULL, x_labels = NULL, col
axis.text.y = element_text(size = 10, color = primary_color)
)
}
```
```{r create_bar_chart-participant-total-trees,echo=TRUE, message=FALSE, fig.height=6, fig.width=8}
create_bar_chart(
survey_data,
field = "Who Planted The Tree(s)? (Required)",
sum_field = "Number of Trees Planted (Required)",
x_labels = c(
"agency" = "State Agency",
"community" = "Community Organization",
@ -440,43 +463,28 @@ create_bar_chart(
"municipality" = "Municipal Government",
"professional" = "Paid Professional"
),
sum_field = "Number of Trees Planted (Required)",
x_title = "Participant Type",
y_title = "Total Trees Planted",
title = "Total Trees Planted by Participant Type",
color_palette = c("#233f2b", "#7e9084", "#d9e1dd", "#face00"))
```
```{r func-create_summary_table, echo=TRUE}
```{r func-create-summary-table, echo=TRUE}
create_summary_table <- function(data, field, sum_field, remove_na = TRUE, table_font_size = 14) {
# Input validation
if (!field %in% colnames(data)) {
stop(paste("Error: Field", field, "does not exist in the data"))
}
if (!field %in% colnames(data)) stop(paste("Error: Field", field, "does not exist in the data"))
if (!sum_field %in% colnames(data)) stop(paste("Error: Sum field", sum_field, "does not exist in the data"))
if (!is.numeric(data[[sum_field]]) && !is.integer(data[[sum_field]])) stop(paste("Error: Sum field", sum_field, "is not numeric"))
if (!sum_field %in% colnames(data)) {
stop(paste("Error: Sum field", sum_field, "does not exist in the data"))
}
# Check if sum_field is numeric
if (!is.numeric(data[[sum_field]]) && !is.integer(data[[sum_field]])) {
stop(paste("Error: Sum field", sum_field, "is not numeric"))
}
# Summarize the data based on the field and sum_field provided
summary_data <- data %>%
group_by(!!sym(field)) %>% # Dynamically use the provided field name
group_by(.data[[field]]) %>%
summarise(
submissions = n(), # Count of submissions
total_value = sum(!!sym(sum_field), na.rm = remove_na) # Sum of the specified field
submissions = n(),
total_value = sum(.data[[sum_field]], na.rm = remove_na)
) %>%
mutate(
submissions_percentage = submissions / sum(submissions) * 100, # Proportion of submissions
value_percentage = total_value / sum(total_value) * 100 # Proportion of summed field
)
# Format the table to display commas for the totals and round percentages
summary_data_formatted <- summary_data %>%
submissions_percentage = submissions / sum(submissions) * 100,
value_percentage = total_value / sum(total_value) * 100
) %>%
mutate(
submissions = scales::comma(submissions),
total_value = scales::comma(total_value),
@ -484,8 +492,7 @@ create_summary_table <- function(data, field, sum_field, remove_na = TRUE, table
value_percentage = paste0(round(value_percentage, 1), "%")
)
# Create and style the table with customizable font size and other options
summary_data_formatted %>%
summary_data %>%
knitr::kable(
col.names = c(field, "Number of Submissions", paste("Total", sum_field), "Proportion of Submissions (%)", "Proportion of Sum Field (%)"),
caption = paste("Summary of Submissions and", sum_field, "by", field),
@ -497,31 +504,32 @@ create_summary_table <- function(data, field, sum_field, remove_na = TRUE, table
bootstrap_options = c("striped", "hover"),
font_size = table_font_size
) %>%
kableExtra::column_spec(1, width = "20em", bold = TRUE) %>% # First column bold and wider
kableExtra::column_spec(2, width = "12em") %>% # Submissions column
kableExtra::column_spec(3, width = "12em") %>% # Total value column
kableExtra::column_spec(1, width = "20em", bold = TRUE) %>%
kableExtra::column_spec(2:3, width = "12em") %>%
kableExtra::add_footnote("The proportions represent the percentage of submissions and sum of the field for each category relative to the overall dataset.")
}
```
The following table provides a breakdown of the total number of trees planted by participant type. It shows both the total number of trees planted by each group and their proportional contribution to the overall planting efforts. This information helps assess which participant types have contributed the most to the tree planting program.
### Participant Type Table
```{r participant-type-table, echo=TRUE, message=FALSE, fig.height=6, fig.width=8}
This table presents a detailed summary of tree planting activity by participant group, showing both the number of submissions and the total trees planted. The percentage columns offer a clear view of each groups relative contribution to both participation and total planting, which helps evaluate equity and engagement across the initiative.
```{r participant-type-table, echo=TRUE}
survey_data %>%
mutate(
`Who Planted The Tree(s)? (Required)` = recode(`Who Planted The Tree(s)? (Required)`,
mutate(`Who Planted The Tree(s)? (Required)` = recode(`Who Planted The Tree(s)? (Required)`,
"agency" = "State Agency",
"community" = "Community Organization",
"landowner" = "Private Landowner",
"municipality" = "Municipal Government",
"professional" = "Paid Professional")
) %>%
"professional" = "Paid Professional")) %>%
create_summary_table("Who Planted The Tree(s)? (Required)", "Number of Trees Planted (Required)", remove_na = FALSE, table_font_size = 16)
```
## Named User Activity
```{r named-user-activity-table, echo=TRUE, message=FALSE, fig.height=6, fig.width=8}
This table breaks down the number of submissions and trees planted by named users, typically representing staff accounts or recurring contributors. Public (anonymous) users are grouped separately. This view is useful for recognizing heavy contributors and assessing platform usage patterns.
```{r named-user-activity-table}
survey_data %>%
mutate(Creator = ifelse(is.na(Creator), "Public User", Creator)) %>%
create_summary_table("Creator", "Number of Trees Planted (Required)", remove_na = FALSE, table_font_size = 16)
@ -529,14 +537,17 @@ survey_data %>%
## Unique E-mail Activity
```{r unique-email-activity-table, echo=TRUE, message=FALSE, fig.height=6, fig.width=8}
This table summarizes the planting activity associated with unique email addresses submitted via the optional contact field. It helps assess how many individuals are participating and the extent of their contributions. Since providing an email is optional, this data may also reflect comfort levels with contact sharing.
```{r unique-email-activity-table}
survey_data %>%
mutate(Creator = ifelse(is.na(`Planter Contact Email (Optional)`), "Not Provided", `Planter Contact Email (Optional)`)) %>%
mutate(`Planter Contact Email (Optional)` = ifelse(is.na(`Planter Contact Email (Optional)`), "Not Provided", `Planter Contact Email (Optional)`)) %>%
create_summary_table("Planter Contact Email (Optional)", "Number of Trees Planted (Required)", remove_na = FALSE, table_font_size = 16)
```
## Municipal Activity
### Municipal Activity
This table presents the number of trees planted by self-reported municipality. It accounts for formatting variations such as town/city/village prefixes. These insights are valuable for understanding geographic participation and for identifying municipalities that may need additional support or engagement.
```{r municipal-activity-table}
survey_data %>%
@ -547,9 +558,13 @@ survey_data %>%
TRUE ~ `Participant Municipality (Optional)`
)) %>%
create_summary_table("Participant Municipality (Optional)", "Number of Trees Planted (Required)", remove_na = FALSE, table_font_size = 16)
```
## Organizaiton Activity
### Organization Activity
This table highlights planting contributions by named organizations, either selected from a predefined list or entered manually by participants. Its useful for identifying high-performing organizations, recognizing partners, and exploring collaboration opportunities. It also helps validate the effectiveness of predefined organization lists in the survey tool.
```{r organization-activity-table}
survey_data %>%
inner_join(participant_organizations, by = c("GlobalID" = "ParentGlobalID")) %>%