Clean Ports Survey: What do youth in the Bay Area think about the Port of Oakland?

Getting Started

Loading in Libraries

Loading in the Data Set

About the Data

Survey responses were collected from August 27, 2024 through December 29, 2025. The survey was distributed via Google Forms and shared broadly across our networks of Bay Area youth, including program alumni and participants, through social media channels, and via in-person and digital outreach efforts.

To ensure data quality, we filtered out responses identified as spam or bot-generated. We also removed x responses from non-youth. After data cleaning and several rounds of verification checks, we retained 338 valid English responses and 11 valid Spanish responses for a total of 349. While we have taken extensive measures to verify response authenticity, we acknowledge that absolute certainty is not possible.

Data Cleaning

Code
#Column Name Cleaning
#Renaming columns because they are so long

responses <- responses |> 
  rename(
    gender_pronouns = Gender.Pronouns,
    school_org = School.or.Organization..put.n.a.if.not.applicable.,
    gender = Gender...Gender.Identity....This.information.will.be.for.reporting.purposes.only..,
    race_ethnicity = Race.Ethnicity...Please.select.the.one.you.most.identify.with...This.information.will.be.for.reporting.purposes.only...,
    free_reduced_lunch = Do.you.your.family.qualify.for.free.reduced.lunch.,
    volunteer_interest = Would.you.be.interested.in.volunteering.with.the.NVR.Program.,
    heard = Have.you.heard.of.the.Port.of.Oakland.,
    been = Have.you.ever.been.to.the.Port.of.Oakland.or.Port.of.Oakland.properties.,
    toured = Have.you.ever.toured.the.Port.of.Oakland.,
    harbor = Have.you.ever.participated.in.a.Port.of.Oakland.Harbor.Tour.,
    wider_impact = How.do.you.think.the.Port.of.Oakland.impacts.the.wider.Oakland.community.,
    maritime_knowledge = Do.you.know.what.maritime.industry.is..If.not..what.do.you.think.it.is..,
    oakland_overall_trade = How.do.you.think.Oakland.is.connected.to.the.overall.global.trade.and.maritime.industry.,
    port_of_oakland_connects_bay = How.does.the.Port.of.Oakland.connect.the.Bay.Area.to.global.trade.and.maritime.industry.,
    local_climate_impact = Do.you.think.the.Port.of.Oakland.is.impacting.the.local.climate.environment..Is.yes..why..If.no..why.not..,
    how_to_reduce_climate_impact = If.you.answered.yes.above..how.can.the.Port.of.Oakland.decrease.their.impacts.on.the.local.climate.and.environment...,
    electrification_impact = Do.you.think.electrification.will.help.decrease.climate.environmental.impacts.of.the.Port.of.Oakland..Electrification.is.the.process.of.switching.gas.and.diesel.powered.appliances.to.electric.,
    what_do_you_want_to_learn_more = What.do.you.want.to.learn.more.about.related.to.the.Port.of.Oakland.,
    employment_consideration = Would.you.ever.consider.employment.with.the.Port.of.Oakland.,
    training_requests = What.type.of.trainings.or.skills.would.be.helpful.for.you.or.the.wider.community.to.explore.employment.opportunities.with.the.Port.of.Oakland.,
    electrification_funding_knowledge = Did.you.know.the.Port.of.Oakland.received.over..322.million.dollars.to.support.in.electrification.of.the.Port.of.Oakland.and.Port.of.Oakland.properties.,
    following_socials = Do.you.follow.the.Port.on.social.media..Which.accounts..Why.,
    website_visit = Have.you.ever.gone.to.the.Port.of.Oakland.website..Why.,
    newsletter = Did.you.know.the.Port.of.Oakland.has.a.newsletter...Are.you.signed.up..Why.,
    school_county = What.county.is.your.school.in.,
    person_of_color = Do.you.identify.as.a.person.of.color.,
    found_survey = How.did.you.find.out.about.this.event.,
    three_words = When.you.think.of.the.Port.of.Oakland..what.do.you.think.of..Please.list.at.least.3.words.or.phrases., 
    importance_to_community = Do.you.think.the.Port.of.Oakland.is.important.to.the.Oakland.Community..Why.or.Why.not.
    )
Code
#Renaming the response "Another Identity (Please specify in next field)" to just "Another identity"
responses <- responses %>%
  mutate(gender = case_when(
    gender == "Another identity (Please specify in next field)" ~ "Another identity",
    TRUE ~ gender
  ))

Demographic Analysis: Who filled out our survey?

A Breakdown of Survey Respondents by Age and Gender

Across respondents under 30 years old- our age group breakdown shows we mainly reached participants in the high school aged group (~49% of respondents were aged 0-17) and around 40% of participants were ages 18-24 and only about 10% were between 25-30.

We tracked a higher percent of female participants (~52%), followed by male participants (~43%) as well as non-binary/trans/different responses.

Code
#Standardizing ages

responses <- responses |> 
  mutate(Age = case_when(
    Age %in% c("0 - 13", "13 - 17", "14 - 17") ~ "0-17",
    Age %in% c("18-24", "18 - 24") ~ "18-24",
    TRUE ~ Age
  ))

#
library(dplyr)

# Calculate percentages
age_summary <- responses |> 
  count(Age) |> 
  mutate(percent = n / sum(n) * 100,
         label = paste0(Age, "\n(", round(percent, 1), "%)"))
gender_summary <- responses |> 
  count(gender) |> 
  mutate(percent = n / sum(n) *100,
         label = paste0(gender, "\n(", round(percent, 1), "%)"))

ggplot(data=responses, mapping = aes(x=Age, fill=gender)) +
  geom_bar() +
  scale_x_discrete(labels = setNames(age_summary$label, age_summary$Age)) +
  scale_fill_brewer(palette = "Set2", labels = setNames(gender_summary$label, gender_summary$gender)) +
  theme_minimal() +
  theme(
    text = element_text(family = 'serif', size = 14),
    plot.title = element_text(family = "serif", size = 16),
    plot.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.border = element_blank(),  # Remove frame
    axis.text.x = element_text(angle = 0, hjust = 0.5, 
                               margin = margin(t = 10)),  # Add space above labels
    axis.title.x = element_text(margin = margin(b =20, t = 20)),  # Space above x-axis title
    axis.title.y = element_text(margin = margin(l = 20, r = 10)), # Space to right of y-axis title
    panel.spacing = unit(2, "lines")  # General spacing
  ) +
  labs(
    x = 'Age Group',
    y = 'Count',
    fill = 'Gender'
  )

A Breakdown of Survey Respondents by City

The graph below shows cities that appeared at least twice in our data. The survey received responses from multiple cities across the region. Oakland had the highest participation with 198 respondents, followed by Berkeley with 64. The remaining top cities showed considerably lower representation, ranging from 2 to 12 respondents each, including Richmond (12), San Leandro (10), and San Francisco (8). This distribution reflects strong concentration of responses from the Oakland-Berkeley area.

Code
#City Column Clean

#cities with common dupes
main_cities <- c("Oakland", "Richmond", "Berkeley", "San Francisco", 
                 "Pittsburg", "San Leandro", "San Pablo", "Pinole", 
                 "Hercules", "Emeryville", "Alameda")

find_city_match <- function(city_text, city_list){
  cleaned <- city_text |> 
    str_to_lower() |> 
    str_trim() |> 
    str_remove("(,.*|\\s+ca.*)$") |> 
    str_squish()
  
  city_list_lower <- str_to_lower(city_list)
  
  exact_match <- city_list[city_list_lower == cleaned]
  if (length(exact_match) > 0) return(exact_match[1])
  
  #distances of characters from cleaned to our list of main cities
  distances <- adist(cleaned, city_list_lower) # gives you distances between cleaned and cities
  best_match_idx <- which.min(distances) # gives you the index of the city with min val
  min_distance <- min(distances) # gives you vectors with min vals
  
  if(min_distance <= 2) {
    return(city_list[best_match_idx])
  }
  return(str_to_title(cleaned))
}

responses <- responses |> 
  mutate(City = sapply(City, find_city_match, city_list = main_cities))


city_counts <- responses |> 
  count(City) |> 
  filter(n>=2)

responses |> 
  filter(City %in% city_counts$City) |> 
  ggplot(aes(y=fct_rev(fct_infreq(City)))) +
  geom_bar(fill = "#FC8D62FF") +
  geom_text(stat='count', aes(label=after_stat(count)), hjust=-0.2, 
            family = 'serif', size = 4) +
  scale_x_continuous(expand = expansion(mult = c(0, 0.1)))+
  theme_minimal() +
  theme(
    text = element_text(family = 'serif', size = 14),
    plot.title = element_text(family = "serif", size = 16),
    plot.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.border = element_blank(),
    axis.text.y = element_text(margin = margin(r = 10)),
    axis.title.x = element_text(margin = margin(b = 5, t = 10)),
    axis.title.y = element_text(margin = margin(l = 5, r = 5)),
    panel.spacing = unit(2, "lines")
  ) +
  labs(
    y = 'City',
    x = 'Count'
  )

Assessing Knowledge: What do people know about the Port of Oakland?

Do people know where the Port of Oakland is located? (Answer: kind of)

Close to 40% of respondents indicated they were unsure of the Port’s location. About half (46.4%) mentioned Oakland generally. More specifically, ~14% mentioned West Oakland, ~9% referenced Jack London Square, and 0.9% specifically mentioned Middle Harbor. 9.6% provided other responses (e.g., Alameda, San Francisco, California, etc.).

Code
#Where is the Port of Oakland located?
responses <- responses %>%
  mutate(
    response_lower = str_to_lower(str_trim(`Where.is.the.Port.of.Oakland.located..Please.put..not.sure..if.you.are.unsure.`)),
    # Remove extra spaces
    response_lower = str_squish(response_lower),
    
    # Check for each mention (can have multiple)
    mentions_not_sure = str_detect(response_lower, "not\\s*sure|notsure|n/a|idk|don'?t\\s*know|dont\\s*know|not\\s*totally\\s*sure|assuming|presumably|guessing|unsure") | str_detect(response_lower, "^n$"),
    mentions_oakland = str_detect(response_lower, "oak\\s*land|oakland"),
    mentions_west_oakland = str_detect(response_lower, "west\\s*oak\\s*land|westoakland|west\\s*oakland"),
    mentions_jack_london = str_detect(response_lower, "jack\\s*london|jacklondon"),
    mentions_middle_harbor = str_detect(response_lower, "middle\\s*harbor|middleharbor"),
    
    # Check if none of the above were mentioned
    mentions_other = !mentions_not_sure & !mentions_oakland & !mentions_west_oakland & !mentions_jack_london & !mentions_middle_harbor
  )
# Summary statistics - count and percentage for each mention
summary_stats <- responses %>%
  summarise(
    total_responses = n(),
    not_sure = sum(mentions_not_sure),
    not_sure_pct = round(100 * not_sure / total_responses, 1),
    oakland = sum(mentions_oakland),
    oakland_pct = round(100 * oakland / total_responses, 1),
    west_oakland = sum(mentions_west_oakland),
    west_oakland_pct = round(100 * west_oakland / total_responses, 1),
    jack_london = sum(mentions_jack_london),
    jack_london_pct = round(100 * jack_london / total_responses, 1),
    middle_harbor = sum(mentions_middle_harbor),
    middle_harbor_pct = round(100 * middle_harbor / total_responses, 1),
    other = sum(mentions_other),
    other_pct = round(100 * other / total_responses, 1)
  )
# Create a tidy summary for easy reading
summary_tidy <- tibble(
  mention = c("Not Sure", "Oakland", "West Oakland", "Jack London", "Middle Harbor", "Other"),
  count = c(summary_stats$not_sure, summary_stats$oakland, summary_stats$west_oakland, 
            summary_stats$jack_london, summary_stats$middle_harbor, summary_stats$other),
  percentage = c(summary_stats$not_sure_pct, summary_stats$oakland_pct, 
                 summary_stats$west_oakland_pct, summary_stats$jack_london_pct,
                 summary_stats$middle_harbor_pct, summary_stats$other_pct)
) %>%
  arrange(desc(count))
# Print results
cat("MENTIONS BREAKDOWN:\n")
MENTIONS BREAKDOWN:
Code
for(i in 1:nrow(summary_tidy)) {
  cat(sprintf("  %-20s %4d  (%.1f%%)\n", 
              paste0(summary_tidy$mention[i], ":"),
              summary_tidy$count[i], 
              summary_tidy$percentage[i]))
}
  Oakland:              159  (46.4%)
  Not Sure:             139  (40.5%)
  West Oakland:          48  (14.0%)
  Other:                 32  (9.3%)
  Jack London:           29  (8.5%)
  Middle Harbor:          3  (0.9%)

Have youth heard of the Port of Oakland? (Answer: kind of)

Among 349 survey respondents, awareness and engagement with the Port of Oakland varied considerably. The majority (57.7%) had heard of the Port, while 26.2% had physically visited it. Direct engagement was lower, with 10.2% having toured the Port facilities and 6.4% having participated in a harbor tour.

This tells us: 42.3% of respondents learned about the Port of Oakland through this survey.

Code
library(dplyr)

# Calculate percentages at each stage
funnel <- data.frame(
  Stage = c("Heard of Port", "Been to Port", "Toured Port", "Harbor Tour"),
  Count = c(
    sum(responses$heard == "Yes", na.rm = TRUE),
    sum(responses$been == "Yes", na.rm = TRUE),
    sum(responses$toured == "Yes", na.rm = TRUE),
    sum(responses$harbor == "Yes", na.rm = TRUE)
  )
) %>%
  mutate(
    Percent = Count / nrow(responses) * 100,
    Stage = factor(Stage, levels = Stage)
  )

ggplot(funnel, aes(x = Stage, y = Count)) +
  geom_bar(stat = "identity", fill = "#66C2A5", width = 0.7) +
  geom_text(aes(label = paste0(Count, "\n(", round(Percent, 1), "%)")), 
            vjust = -0.5, family = 'serif', size = 4) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
  theme_minimal() +
  theme(
    text = element_text(family = 'serif', size = 14),
    plot.title = element_text(family = "serif", size = 16, margin = margin(b = 5, t = 10)),
    plot.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.border = element_blank(),
    axis.text.x = element_text(angle = 0, hjust = 0.5, margin = margin(b = 10)),   
    axis.text.y = element_text(margin = margin(r = 10, l = 10)),     
    axis.title.x = element_text(margin = margin(b = 5, t = 5)),     
    axis.title.y = element_text(margin = margin(l = 5, r = 5))
  ) +
  labs(
    title = "Port of Oakland Awareness and Engagement",     
    subtitle = "Out of 349 survey respondents",   
    x = NULL,
    y = "Number of Respondents"
  )

What associations do youth have with the Port of Oakland?

We asked: How do you think the Port of Oakland impacts the wider community?

Respondents identified diverse ways the Port of Oakland affects the wider community. The most frequently mentioned impact was jobs and economic contributions, followed by trade and connectivity benefits. Environmental and health concerns were also prominent themes, alongside responses indicating uncertain or limited knowledge about the Port’s role. Additional themes included community infrastructure, traffic and noise impacts, and various other considerations. This distribution reveals that while many recognize the Port’s economic importance, concerns about environmental impacts and gaps in public awareness remain significant.

Here is a visual and breakdown of the major themes:

Code
#Select question

wider_com <- responses %>%
  transmute(impact = wider_impact)

#Remove blank/NA and read in stopwords
wider_com <- wider_com |> filter(!is.na(impact), str_trim(impact) != "")

data("stop_words")


### Simple Theme Tagging

themes <- wider_com |>
  mutate(theme = case_when(
    # Jobs & Economy (keep as is)
    str_detect(str_to_lower(impact), 
               "job|employment|economic|business|commerce|income|economy|creates jobs|brings jobs|opportunities|worker|career|wage|work|investment|money|fund|revenue") 
    ~ "Jobs/Economy",
    
    # Environmental/Health Issues (expand)
    str_detect(str_to_lower(impact), 
               "air quality|air pollution|pollution|polluter|polluters|environment|health|emission|diesel|toxic|environmental|fuel|polution|burning|sick|water|environment") 
    ~ "Environment/Health",
    
    # Traffic & Noise
    str_detect(str_to_lower(impact), 
               "traffic|noise|truck|congest|highway|commute") 
    ~ "Traffic/Noise",
    
    # Trade & Global Connections
    str_detect(str_to_lower(impact), 
               "shipping|import|export|global|international|trade|market|supply|cargo|connects|ship|goods|products|deliver|resources|overseas|connect|transportation|travel|travels|goods|packages") 
    ~ "Trade/Connectivity",
    
    # Community & Infrastructure (expand)
    str_detect(str_to_lower(impact), 
               "community|neighborhood|resident|infrastructure|identity|services|local|housing|school|living|real estate|skyline|families|people|cultural") 
    ~ "Community/Infrastructure",
    
    # Awareness/Knowledge
    str_detect(str_to_lower(impact), 
               "not sure|don't know|unsure|unclear|no idea|learning|hearing|no clue|n/a|uncertain|i dont know|i don't know|idk|IDK|wouldn't know") 
    ~ "Uncertain/Limited Knowledge",
    
    TRUE ~ "Other"
  ))


library(crosstalk)
library(plotly)
library(DT)

# Create shared data
sd <- SharedData$new(themes)

# Plot
p <- plot_ly(sd, y = ~theme) |>
  add_histogram() |>
  layout(title = "Click bars to filter responses",
      yaxis = list(
      title = "Number of Responses",
      categoryorder = "total ascending"  # orders bars by frequency
    ))

# Table showing individual responses
dt <- datatable(sd, 
                options = list(pageLength = 10),
                selection = 'none',
                )

# Display both
bscols(
  widths = 12,  # full width for each
  p, 
  dt
)

3 words that come up when you think about the Port of Oakland?

Here are the top words in a bar graph and wordcloud:

When asked to provide three words that come to mind about the Port of Oakland, respondents’ associations centered primarily on maritime infrastructure and operations. “Ship” was the most frequently mentioned term (134 times), followed by “cargo” (63) and “water” (57). Physical elements like “boat,” “container,” and “crane” also featured prominently. Economic terms such as “trade,” “economy,” “import,” and “export” appeared with moderate frequency, while “pollution” emerged as a notable concern (26 mentions). The word cloud reflects a strong association with the Port’s functional and physical characteristics, alongside some awareness of its economic role and environmental impact.

Code
# Load stop words
data("stop_words")

# Process directly from responses
unigrams <- responses |>
  filter(!is.na(three_words), str_trim(three_words) != "") |>
  mutate(three_words = str_to_lower(three_words)) |>
  unnest_tokens(word, three_words) |>
  mutate(lemma = lemmatize_words(word)) |>
  filter(str_detect(lemma, "[a-z]"), nchar(lemma) > 2) |>
  anti_join(stop_words, by = c("lemma" = "word")) |>
  count(lemma, sort = TRUE)

#I need a table like unigrams but filtered where n > 20
top_uni <- unigrams |> slice_max(n, n = 20)
top_uni
            lemma   n
1            ship 134
2           cargo  63
3           water  57
4            boat  55
5       container  55
6         oakland  42
7           crane  37
8           trade  32
9            port  31
10      pollution  26
11          ocean  19
12      community  14
13       shipment  14
14            bay  13
15         import  13
16        economy  11
17     industrial  11
18           busy  10
19         export  10
20          crate   8
21         harbor   8
22       industry   8
23            sea   8
24 transportation   8
25     waterfront   8
Code
ggplot(data = top_uni, mapping = aes(x= n, y = (fct_reorder(lemma, n))))+
  geom_col(fill ="#66C2A5")+
  theme_minimal()+
  theme(
    text = element_text(family = 'serif', size = 14),
    plot.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.background = element_rect(fill = "#F5F5F0", color = NA),
    panel.border = element_blank(),
    axis.text.y = element_text(margin = margin(r = 10)),
    axis.title.x = element_text(margin = margin(b = 5, t = 10)),
    axis.title.y = element_text(margin = margin(l = 5, r = 10)),
  ) +
  labs(
    y = 'Most Common Words',
    x = 'Count'
    )

Code
library(wordcloud2)

wordcloud2(data = unigrams |> slice(-(1:15)),
           fontFamily = "Arial",
           color = "random-dark")

Do you think the Port of Oakland is important to the Oakland Community?

Out of 349 responses, the vast majority viewed the Port positively, primarily citing:

  • Jobs/Economy: Respondents emphasized employment opportunities and economic benefits. Representative response: “Yes, it provides jobs, supports local businesses, and boosts the economy through trade.”

  • Trade/Connectivity: Many recognized the Port’s role in importing goods and connecting Oakland globally.

  • Environment/Health concerns: A notable minority raised concerns about pollution and air quality, often alongside economic benefits (“Mixed” sentiment).

  • Some respondents acknowledged unfamiliarity with the Port.

Code
classify_response <- function(text) {
  text_lower <- tolower(text)
  
  # Check for negative/uncertain responses
  if (grepl("^no[^t]|^no$|^no,|not important|not sure|uncertain|i don't know|idk|n/a|^n$", text_lower)) {
    return("Negative/Uncertain")
  }
  
  # Check for mixed responses (mentions both positive and negative)
  has_positive <- grepl("jobs|econom|trade|import|export|goods|shipping|revenue", text_lower)
  has_negative <- grepl("pollut|emission|health|air quality|noise|hazard", text_lower)
  
  if (has_positive && has_negative) {
    return("Mixed")
  }
  
  # Check for positive responses
  if (grepl("^yes|important|definitely|absolutely|of course|crucial|vital", text_lower) || has_positive) {
    return("Positive")
  }
  
  return("Uncertain")
}

responses <- responses %>%
  mutate(sentiment = map_chr(importance_to_community, classify_response))

# --- THEME EXTRACTION ---

extract_themes <- function(text) {
  text_lower <- tolower(text)
  themes <- c()
  
  if (grepl("job|employ|work|career", text_lower)) themes <- c(themes, "Jobs/Employment")
  if (grepl("econom|revenue|money|tax|business|financial", text_lower)) themes <- c(themes, "Economy")
  if (grepl("trade|import|export|shipping|goods|cargo|container|deliver", text_lower)) themes <- c(themes, "Trade/Shipping")
  if (grepl("pollut|emission|air|environment|health|asthma|noise", text_lower)) themes <- c(themes, "Environmental Concerns")
  if (grepl("communit|identity|pride|landmark|icon|history|culture", text_lower)) themes <- c(themes, "Community Identity")
  if (grepl("connect|world|international|global|overseas", text_lower)) themes <- c(themes, "Global Connection")
  
  if (length(themes) == 0) themes <- "Other/Unspecified"
  
  return(paste(themes, collapse = "; "))
}

responses <- responses %>%
  mutate(themes = map_chr(importance_to_community, extract_themes))

sentiment_summary <- responses %>%
  count(sentiment) %>%
  mutate(pct = n / sum(n) * 100)

ggplot(sentiment_summary, aes(x = reorder(sentiment, -n), y = n, fill = sentiment)) +
  geom_col() +
  geom_text(aes(label = paste0(n, " (", round(pct, 1), "%)")), vjust = -0.5) +
  scale_fill_manual(values = c("Positive" = "#2E8B57", 
                                "Mixed" = "#DAA520", 
                                "Negative/Uncertain" = "#CD5C5C",
                                "Uncertain" = "#808080")) +
  labs(title = "Overall Sentiment Toward Port of Oakland",
       subtitle = "How respondents view the port's importance to the community",
       x = NULL, y = "Number of Responses") +
  theme_minimal() +
  theme(legend.position = "none",
        plot.title = element_text(face = "bold"))

Code
responses %>%
  select(importance_to_community, sentiment, themes) %>%
  datatable(
    filter = "top",
    options = list(pageLength = 5),
    colnames = c("Response", "Sentiment", "Themes"),
    caption = "Community Responses: Port of Oakland Importance"
  )

Maritime and Trade Knowledge

Participants were asked about their knowledge of the maritime industry.

Just over half of respondents (55.4%) reported accurate knowledge about the maritime industry, while 23.0% indicated no knowledge and 21.6% expressed unclear or uncertain understanding. These results suggest a significant knowledge gap among nearly half of respondents.

Code
library(dplyr)
library(stringr)

# Classify responses
responses <- responses %>%
  mutate(
    response_lower = str_to_lower(maritime_knowledge),
    
    # Classify knowledge level
    knowledge_type = case_when(
      # Clear "no" or "don't know" responses
      str_detect(response_lower, "^no[,.]?$|^n$|^nope|^no i don|i don't know|i do not know|not sure|never heard|no idea|idk|im not sure|i'm not sure|No I do not") ~ "No/Don't Know",
      
      # Accurate understanding (mentions key concepts)
      str_detect(response_lower, "ship|cargo|port|trade|transport|import|export|sea|ocean|logistics|goods|freight") ~ "Knows (Accurate)",
      
      # Everything else
      TRUE ~ "Unclear/Other"
    )
  )

# Summary table
summary_table <- responses %>%
  count(knowledge_type) %>%
  mutate(percent = round(n / sum(n) * 100, 1))

print(summary_table)
    knowledge_type   n percent
1 Knows (Accurate) 190    55.4
2    No/Don't Know  79    23.0
3    Unclear/Other  74    21.6
Code
unclear_responses <- responses %>%
  filter(knowledge_type == "Unclear/Other") %>%
  select(maritime_knowledge)

Participants were asked: “How does Oakland connect to overall trade?”

Most respondents (approximately 80%) demonstrated a basic understanding of Oakland’s connection to global trade, recognizing the Port of Oakland as the primary link, although many responses were vague (‘it’s connected through the port’) without elaborating on how or why this matters to the community. The most common themes included:

  • Import/export hub - Respondents frequently described Oakland as a gateway for goods moving in and out of the U.S.

  • Asia-Pacific connection - Many specifically mentioned trade with Asia, particularly China, Japan, and South Korea

  • West Coast significance - Several noted Oakland’s role as one of the largest/busiest ports on the West Coast or in Northern California

  • Supply chain role - Some described how goods arrive by ship and are distributed inland via truck and rail

About 15-20% were unsure or unfamiliar with Oakland’s trade connections. A small number offered more nuanced responses, mentioning specific goods (agriculture, electronics, weapons), competition from other ports (LA, Seattle), or historical context.

Code
knowledge_level <- responses |>
  mutate(level = case_when(
    str_detect(str_to_lower(oakland_overall_trade), 
               "\\bidk\\b|not sure|unsure|don't know|do not know|no idea|\\bn/a\\b|\\bna\\b|no clue|never heard|wouldn't know|i'm unsure|see above|see previous|^\\^|^n$|^na$|^port$") |
    str_length(oakland_overall_trade) < 10 ~ "Don't Know",
    TRUE ~ "Basic Understanding"
  ))

summary_table_knowledge <- knowledge_level %>%
  count(level) %>%
  mutate(percent = round(n / sum(n) * 100, 1))

print(summary_table_knowledge)
                level   n percent
1 Basic Understanding 280    81.6
2          Don't Know  63    18.4

Participants were asked about their understanding of how the Port of Oakland connects the Bay Area to global trade and maritime industry:

Most respondents understood the port’s basic function as a trade hub, though around 23% were unsure. A smaller subset demonstrated deeper knowledge of specific trade routes (Asia) or industries (agriculture, tech).

Code
responses <- responses |>
  mutate(
    knows = case_when(
      str_detect(str_to_lower(port_of_oakland_connects_bay), 
                 "\\bidk\\b|not sure|unsure|don't know|do not know|no idea|\\bn/a\\b|no clue|never heard|i'm unsure|^n$|^na$|^port$|^yes$|see above|see previous|^\\^") |
        str_length(port_of_oakland_connects_bay) < 15 ~ "Don't Know",
      TRUE ~ "Has Understanding"
    )
  )

# Count and percentage
responses |> 
  count(knows) |> 
  mutate(pct = round(n/sum(n)*100, 1))
              knows   n pct
1        Don't Know  79  23
2 Has Understanding 264  77

Climate Associations

We asked youth: Do you think the Port of Oakland is impacting the local climate environment?

The overwhelming majority of respondents (90%) believe the Port of Oakland is impacting the local climate and environment, with only 4% saying no and 6% unsure.

Among those who said yes, the most commonly cited concerns were:

  • Air pollution - Emissions from ships, trucks, and cargo equipment were the dominant concern

  • Fossil fuels/greenhouse gases - Many specifically mentioned CO2, diesel, and climate change contributions

  • Water pollution - Oil spills, runoff, and impacts on marine ecosystems

  • Health impacts - Several connected pollution to asthma and respiratory issues in nearby communities (West Oakland, Chinatown)

  • Noise and traffic

There is strong consensus among youth that the port has environmental impacts.

Code
responses <- responses |>
  mutate(
    believes_impact = case_when(
      str_detect(str_to_lower(local_climate_impact), "^no[^t]|^no$|^no,|don't think so|i don't think") ~ "No",
      str_detect(str_to_lower(local_climate_impact), "not sure|idk|don't know|no clue|unsure|^n/a|maybe\\?") ~ "Unsure",
      TRUE ~ "Yes"
    )
  )

responses |> count(believes_impact) |> mutate(pct = round(n/sum(n)*100, 1))
  believes_impact   n  pct
1              No  13  3.8
2          Unsure  21  6.1
3             Yes 309 90.1

When asked how they think the Port can reduce climate impact:

When asked how the Port of Oakland can reduce its environmental impact, the majority of respondents (~50%) suggested electrification and renewable energy solutions, including electric trucks, ships, and equipment, as well as transitioning to solar, wind, or cleaner fuels.

About 30% offered other suggestions, including stricter regulations, pollution monitoring, community engagement, habitat protection, and reducing overall shipping volume. Some respondents specifically mentioned stopping weapons shipments or halting airport expansion as environmental priorities.

Approximately 18% were unsure how to reduce impacts, and a small percentage (~2%) said no, either believing the port wasn’t impacting the environment or that reduction wasn’t possible.

Code
responses <- responses |>
  mutate(
    how_to_reduce_impact = case_when(
      str_detect(str_to_lower(how_to_reduce_climate_impact), "^no[^t]|^no$|^no,|don't think so|i don't think") ~ "No",
      str_detect(str_to_lower(how_to_reduce_climate_impact), "not sure|idk|don't know|no clue|unsure|^n/a|maybe\\?") ~ "Unsure",
      str_detect(str_to_lower(how_to_reduce_climate_impact), "electrify|switch|alternatives|alternative|sustainable|renewable|solar|nuclear|electric|electrification|technology|clean energy|cleaner energy|decarbonize|clean|cleaner|fuel|fuels|green|zero-emission|cleaner fuel|cleaner fuels|zero-emissions") ~ "Electrify/Renewable Energy",
      TRUE ~ "Other"
    )
  )

reduce_impact_summary <- responses |> 
  count(how_to_reduce_impact) |> 
  mutate(pct = round(n/sum(n)*100, 1))

reduce_impact_summary
        how_to_reduce_impact   n  pct
1 Electrify/Renewable Energy 167 48.7
2                         No   5  1.5
3                      Other 110 32.1
4                     Unsure  61 17.8

How can the Port Reduce its environmental impact?

The interactive chart below shows how respondents suggested the Port of Oakland could reduce its environmental impact, grouped by whether they believe the port is currently impacting the environment. Click on bars to filter the table and view individual responses.

Code
# Create shared data
sd <- SharedData$new(responses |> 
                       select(believes_impact, how_to_reduce_impact, how_to_reduce_climate_impact))

# Plot by solution type, colored by belief
p <- plot_ly(sd, y = ~how_to_reduce_impact, color = ~believes_impact) |>
  add_histogram() |>
  layout(
    title = "Click bars to filter responses",
    xaxis = list(title = "Count"),
    yaxis = list(
      title = "",
      categoryorder = "total ascending"
    ),
    barmode = "stack"
  )

# Table
dt <- datatable(sd, 
                options = list(pageLength = 10),
                selection = 'none',
                colnames = c("Believes Impact?", "Solution Category", "Full Response")
)

# Display both stacked
bscols(
  widths = 12,
  p, 
  dt
)

Thoughts on Electrification

We provided a definition for electrification on our survey and asked:

“Do you think electrification will decrease climate environmental impacts of the Port of Oakland?”

Most youth (66%) believe electrification will reduce the Port’s environmental impact, with another 20% saying it might help. Around 4% were skeptical, suggesting broad community support for the Port’s clean energy transition.

Code
#this is a drop down and easy to visualize

ggplot(data = responses, mapping = aes(x = fct_infreq(electrification_impact))) +
  geom_bar(aes(y = after_stat(count/sum(count)*100)), fill = "#66C2A5") +
  geom_text(aes(y = after_stat(count/sum(count)*100), 
                label = paste0(round(after_stat(count/sum(count)*100), 1), "%")),
            stat = "count", hjust = -0.2, size = 3.5) +
  coord_flip() +
  labs(
    title = "Do you think electrification will decrease climate/environmental impacts of the Port?",
    x = "",
    y = "Percent"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(family = 'serif', size = 10)
  ) +
  ylim(0, 100)

We asked about if they were aware of Clean Ports electrification efforts:

Most (~80%) respondents reported that they did not know about the $322 million in funding for electrification but a notable 14 percent did know about it and about 5% were unsure.

This also tells us: 86% of respondents learned about the $322M funding through this survey.

Code
#also a drop down - 
ggplot(data = responses, mapping = aes(x = fct_infreq(electrification_funding_knowledge), fill = electrification_funding_knowledge)) +
  geom_bar(aes(y = after_stat(count/sum(count)*100))) +
  geom_text(aes(y = after_stat(count/sum(count)*100), 
                label = paste0(round(after_stat(count/sum(count)*100), 1), "%")),
            stat = "count", hjust = -0.2, size = 3.5) +
  coord_flip() +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Did you know the Port received $322M for electrification?",
    subtitle = "Awareness of federal/state funding for Port sustainability initiatives",
    x = "",
    y = "Percent"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    plot.title = element_text(size = 12, face = "bold"),
    plot.subtitle = element_text(size = 10, color = "gray40")
  ) +
  ylim(0, 100)

Future Engagement and Opportunities

We asked youth what they wanted to learn more about the Port of Oakland?

There was high engagement with learning interest! When asked what they want to learn about the Port of Oakland, respondents showed strongest interest in environment and sustainability efforts, especially around electrification and pollution reduction. Jobs and careers was the second most common theme, with many asking about employment opportunities, internships, and training programs. Respondents also expressed curiosity about how the port operates, its community impact, and trade/cargo specifics.

Code
library(tidyverse)
library(crosstalk)
library(plotly)
library(DT)

responses <- responses |>
  mutate(
    learn_theme = case_when(
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "^no$|^no,|nothing|not sure|idk|don't know|^na$|^n$|n/a|no thank") ~ "Not Interested/Unsure",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "environment|sustain|green|climate|pollution|emission|clean energy|electri|renewable|eco|carbon") ~ "Environment/Sustainability",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "job|career|work|employ|intern|opportunities|training|pay|paid") ~ "Jobs/Careers",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "how it work|how they work|operate|function|logistics|run|day to day|daily") ~ "Operations/How It Works",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "community|impact|affect|local|resident|neighborhood|health") ~ "Community Impact",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "history|started|founded|when was") ~ "History",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "cargo|goods|ship|import|export|trade|what comes|what goes") ~ "Trade/Cargo",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "tech|automat|electric truck|crane|equipment|moderniz") ~ "Technology",
      str_detect(str_to_lower(what_do_you_want_to_learn_more), "^yes$|^sure$|everything|anything|more about it") ~ "General Interest",
      TRUE ~ "Other"
    )
  )

# Create shared data
sd <- SharedData$new(responses |> select(learn_theme, what_do_you_want_to_learn_more))

# Plot
p <- plot_ly(sd, y = ~learn_theme, color = I("#66C2A5")) |>
  add_histogram() |>
  layout(
    title = list(
      text = "What Do You Want to Learn About the Port?<br><sup>Click bars to filter responses</sup>",
      font = list(size = 14)
    ),
    xaxis = list(title = "Number of Responses"),
    yaxis = list(
      title = "",
      categoryorder = "total ascending"
    ),
    plot_bgcolor = "white",
    paper_bgcolor = "white",
    margin = list(l = 150)
  )

# Table
dt <- datatable(sd, 
                options = list(
                  pageLength = 10,
                  dom = 'ftp'
                ),
                selection = 'none',
                class = 'compact stripe hover',
                colnames = c("Theme", "Full Response")
)

# Display both
bscols(
  widths = 12,
  p, 
  dt
)

Would you ever consider employment with the Port of Oakland?

Nearly 6 in 10 youth (58%) would consider working at the Port, with the largest group (37%) saying ‘Maybe’ indicating strong potential interest that could be converted through better career information and outreach programs.

Code
ggplot(data = responses, mapping = aes(x = fct_infreq(employment_consideration), fill = employment_consideration)) +
  geom_bar(aes(y = after_stat(count/sum(count)*100))) +
  geom_text(aes(y = after_stat(count/sum(count)*100), 
                label = paste0(round(after_stat(count/sum(count)*100), 1), "%")),
            stat = "count", hjust = -0.2, size = 3.5) +
  coord_flip() +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Would you ever consider employment with the Port of Oakland?",
    x = "",
    y = "Percent"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    plot.title = element_text(size = 12, face = "bold"),
    plot.subtitle = element_text(size = 10, color = "gray40")
  ) +
  ylim(0, 100)

What types of training or skills would be helpful for you or wider community to explore employment with the Port of Oakland?

Youth want hands-on technical training (many respondents noted technical/equipment operations and logistics/maritime operations training), but many don’t know what skills are needed - suggesting an opportunity for the Port to develop clearer career pathway information and expand outreach programs like internships and tours.

Code
responses <- responses |>
  mutate(
    skills_theme = case_when(
      # Not sure / Don't know
      str_detect(str_to_lower( training_requests), "^no$|not sure|idk|don't know|i'm not sure|^n$|^na$|n/a|^\\?$|no clue|not interested") ~ "Not Sure/Don't Know",
      
      # Technical/Equipment skills
      str_detect(str_to_lower( training_requests), "crane|forklift|machinery|equipment|mechanic|maintenance|technical|operat|cdl|driver|truck|welding") ~ "Technical/Equipment Operations",
      
      # Engineering
      str_detect(str_to_lower( training_requests), "engineer|stem|coding") ~ "Engineering/STEM",
      
      # Logistics/Operations
      str_detect(str_to_lower( training_requests), "logistic|supply chain|shipping|cargo|warehouse|maritime|trade|customs|import|export") ~ "Logistics/Maritime Operations",
      
      # Environmental/Sustainability
      str_detect(str_to_lower( training_requests), "environment|sustainab|green|climate|clean energy|electri|eco") ~ "Environmental/Sustainability",
      
      # Safety
      str_detect(str_to_lower( training_requests), "safety|certification|certif") ~ "Safety/Certifications",
      
      # Soft skills
      str_detect(str_to_lower( training_requests), "communication|teamwork|leadership|management|problem.solving|collaboration|soft skill") ~ "Soft Skills/Management",
      
      # Outreach/Awareness/Education
      str_detect(str_to_lower( training_requests), "outreach|awareness|tour|field trip|shadow|intern|workshop|info session|advertisement|marketing|visit|exposure|education|pamphlet|booth") ~ "Outreach/Education Programs",
      
      # Jobs info
      str_detect(str_to_lower( training_requests), "job|employ|opportunit|career|pay|hiring") ~ "Job Information/Opportunities",
      
      TRUE ~ "Other"
    )
  )

# Create shared data
sd <- SharedData$new(responses |> select(skills_theme, training_requests))

# Plot
p <- plot_ly(sd, y = ~skills_theme, color = I("#66C2A5")) |>
  add_histogram() |>
  layout(
    title = list(
      text = "What Types of Tranings Would you Want to Receive from the Port?<br><sup>Click bars to filter responses</sup>",
      font = list(size = 14)
    ),
    xaxis = list(title = "Number of Responses"),
    yaxis = list(
      title = "",
      categoryorder = "total ascending"
    ),
    plot_bgcolor = "white",
    paper_bgcolor = "white",
    margin = list(l = 150)
  )

# Table
dt <- datatable(sd, 
                options = list(
                  pageLength = 10,
                  dom = 'ftp'
                ),
                selection = 'none',
                class = 'compact stripe hover',
                colnames = c("Theme", "Full Response")
)

# Display both
bscols(
  widths = 12,
  p, 
  dt
)

Current Engagement with the Port of Oakland

Code
    website_visit = Have.you.ever.gone.to.the.Port.of.Oakland.website..Why.,
    newsletter = Did.you.know.the.Port.of.Oakland.has.a.newsletter...Are.you.signed.up..Why.,
Code
# 1. Code Yes/No for each engagement type
responses <- responses |>
  mutate(
    follows_socials = case_when(
      str_detect(str_to_lower(following_socials), "^no|i do not|i don't|don't follow|didn't know") ~ "No",
      str_detect(str_to_lower(following_socials), "^yes|instagram|twitter|facebook|tiktok|linkedin|X|x|IG|ig") ~ "Yes",
      TRUE ~ "No"
    ),
    visited_website = case_when(
      str_detect(str_to_lower(website_visit), "^no|never|i have not|haven't") ~ "No",
      str_detect(str_to_lower(website_visit), "^yes|visited|have visited|recently") ~ "Yes",
      TRUE ~ "No"
    ),
    subscribed_newsletter = case_when(
      str_detect(str_to_lower(newsletter), "^no|not signed|didn't know|i am not|never heard") ~ "No",
      str_detect(str_to_lower(newsletter), "^yes|signed up|subscribed|i'll sign|i will") ~ "Yes",
      TRUE ~ "No"
    )
  )

# 2. Create summary for visualization
engagement_summary <- responses |>
  summarise(
    `Following Socials` = sum(follows_socials == "Yes"),
    `Visited Website` = sum(visited_website == "Yes"),
    `Newsletter Subscriber` = sum(subscribed_newsletter == "Yes")
  ) |>
  pivot_longer(everything(), names_to = "Engagement Type", values_to = "Yes") |>
  mutate(
    Total = nrow(responses),
    No = Total - Yes,
    Yes_pct = round(Yes/Total*100, 1)
  )


# Stacked bar 
engagement_long <- engagement_summary |>
  select(`Engagement Type`, Yes, No) |>
  pivot_longer(cols = c(Yes, No), names_to = "Response", values_to = "Count")

ggplot(engagement_long, aes(x = `Engagement Type`, y = Count, fill = Response)) +
  geom_col(position = "fill") +
  scale_fill_manual(values = c("Yes" = "#FC8D62FF", "No" = "#cccccc")) +
  scale_y_continuous(labels = scales::percent) +
  coord_flip() +
  labs(
    title = "Community Engagement with Port of Oakland",
    x = "",
    y = ""
  ) +
  theme_minimal()

I think it would be interesting to see why people say yes

Code
yes_responses <- responses |>
  filter(follows_socials == "Yes" | visited_website == "Yes" | subscribed_newsletter == "Yes") |>
  select(following_socials, website_visit, newsletter) 

datatable(yes_responses,
          options = list(pageLength = 10, dom = 'ftp'),
          colnames = c("Following Socials", "Website Visit", "Newsletter"),
          caption = "Responses from those who engaged with the Port through Socials or Website or Newsletter")

Increase in Knowledge

The survey itself served as an educational tool. Prior to the survey, only 14% of respondents were aware that the Port received $322 million in federal/state funding for electrification - meaning 86% learned about this investment through the survey. Similarly, while 58% had previously heard of the Port of Oakland, 42% of respondents were introduced to the Port through this survey. This highlights both a significant awareness gap and the potential for community outreach to increase knowledge about the Port’s sustainability initiatives and economic importance.