stocksmart
for 2022 SOE reportsAndy renamed the assessmentdata package stocksmart based on Stock SMART.
Two data frames are in the package, stockAssessmentData
and stockAssessmentSummary
.
In stockAssessmentData
we have time series. Columns are StockName, Year, Value, Metric, Description, Units, AssessmentYear, Jurisdiction, FMP, CommonName, ScientificName, ITIS, UpdateType, StockArea, RegionalEcosystem and the reported metrics are Catch, Fmort, Recruitment, Abundance, Index.
datatable(head(stockAssessmentData), rownames = FALSE)
In stockAssessmentSummary
we have assessment metadata. Columns are Stock Name, Jurisdiction, FMP, Science Center, Regional Ecosystem, FSSI Stock?, ITIS Taxon Serial Number, Scientific Name, Common Name, Stock Area, Assessment Year, Assessment Month, Last Data Year, Update Type, Review Result, Assessment Model, Model Version, Lead Lab, Citation, Final Assessment Report 1, Final Assessment Report 2, Point of Contact, Life History Data, Abundance Data, Catch Data, Assessment Level, Assessment Frequency, Assessment Type, Model Category, Catch Input Data, Abundance Input Data, Biological Input Data, Ecosystem Linkage, Composition Input Data, F Year, Estimated F, F Unit, F Basis, Flimit, Flimit Basis, Fmsy, Fmsy Basis, F/Flimit, F/Fmsy, Ftarget, Ftarget Basis, F/Ftarget, B Year, Estimated B, B Unit, B Basis, Blimit, Blimit Basis, Bmsy, Bmsy Basis, B/Blimit, B/Bmsy, MSY, MSY Unit.
datatable(head(stockAssessmentSummary), rownames = FALSE, options = list(scrollX = TRUE))
Build ecodata input spreadsheet from stockAssessmentSummary
and use the ecodata code to make the dataset for plotting:
assess2021 <- stockAssessmentSummary %>%
filter(`Science Center` == "NEFSC") %>%
select(c(`Stock Name`, Jurisdiction, FMP, `Science Center`,
`Stock Area`, `Assessment Year`, `Last Data Year`,
`F Year`, `Estimated F`, Flimit, Fmsy, `F/Flimit`,
`F/Fmsy`, Ftarget, `F/Ftarget`, `B Year`, `Estimated B`,
`B Unit`, Blimit, Bmsy, `B/Blimit`, `B/Bmsy`)) %>%
arrange(Jurisdiction, `Stock Name`, FMP, `Assessment Year`) %>%
rename(Entity.Name = `Stock Name`,
Assessment.Year = `Assessment Year`,
F.Fmsy = `F/Fmsy`,
B.Bmsy = `B/Bmsy`)
write.csv(assess2021, here("assess.csv"))
# from get_stocks.R, ecodata 2020
#assess <- read.csv(file.path(data.dir, "2019assess.csv"))
assess <- assess2021
#decode <- read.csv(file.path(data.dir, "2019decoder.csv"))
decode <- read.csv(here("2020decoder.csv"))
write.csv(decode, here("decoder.csv"))
stock_status_stockSMART <-
assess %>%
dplyr::group_by(Entity.Name) %>%
dplyr::filter(Assessment.Year == max(Assessment.Year)) %>%
#Find last year assessment occurred for each stock
dplyr::ungroup() %>%
dplyr::left_join(.,decode, by = "Entity.Name") %>% #Join in list of managed species
dplyr::select(Entity.Name, Assessment.Year, F.Fmsy, B.Bmsy, Council, Code) %>%
#select column variables to keep
dplyr::mutate(id = 1:length(Entity.Name)) %>%
tidyr::gather(.,Var, Value,-id,-Entity.Name,-Assessment.Year,-Council,-Code) %>%
#wide to long
dplyr::select(-id) %>%
dplyr::rename(`Last assessment` = Assessment.Year,
Stock = Entity.Name) %>% #rename variables for clarity
dplyr::mutate(Units = "unitless") #%>%
#dplyr::mutate(Value = replace(Value, which(Code == "N Windowpane" & Var == "F.Fmsy"), NA))
Then test to see if we see the updates relative to 2020 ecodata. I’m leaving out all the plot annotations for unknown status.
stock_status <-
stock_status_stockSMART %>%
mutate(Code = recode(Code, "Dogfish" = "Sp. Dogfish" )) %>%
spread(.,Var,Value) %>%
filter(Council %in% c("MAFMC","Both")) %>%
group_by(Stock) %>%
mutate(score = case_when(
(B.Bmsy <0.5) ~"a",
(F.Fmsy >1) ~ "a",
(F.Fmsy < 1 & B.Bmsy > 0.5 & B.Bmsy < 1) ~ "b",
(F.Fmsy < 1 & B.Bmsy > 1) ~ "c"))
#Plot constants
y.max <- 2.1 #2.0 mackerel cut off F/Fmsy is 2.08
x.max <- 2.6
#A dataframe that defines custom legend for stocks with unknown status
# unknown <- data.frame(text = c("Unknown Status", "Longfin Squid",
# "Shortfin Squid", "N. Goosefish", "S. Goosefish"),
# x = rep(0.9*x.max,5), y = seq(0.93*y.max,1.5,-.1))
# Custom Color
custom_color<- c("#56B4E9", "#009E73", "#0072B2")
#Plotting code
ggplot(data = stock_status) +
geom_vline(xintercept = 1, linetype = "dotted")+
geom_vline(xintercept = 0.5, linetype = "dashed")+
geom_hline(yintercept = 1, linetype = "dashed") +
geom_point(aes(x = B.Bmsy,
y = F.Fmsy,
shape = Council,
color = score)) +
geom_text_repel(aes(x = B.Bmsy, #geom_text_repel auto-jitters text around points
y = F.Fmsy,
label = Code,
color = score),
show.legend = FALSE, nudge_y = -0.01, nudge_x = 0.05) +
scale_color_brewer(palette = "Dark2",
breaks = stock_status$score) +
ylim(0,y.max) +
xlim(0,x.max) +
# geom_text(data = unknown, aes(x = x, y = y, label = text), #Custom legend for unknown stock status
# size = c(4.75,rep(4,4))) +
# annotate("rect", xmin = 0.8*x.max,
# xmax = x.max,
# ymin = 0.65*y.max,
# ymax = 0.90*y.max,
# alpha = 0.1) +
xlab(expression(~B/B[msy])) +
ylab(expression(~F/F[msy])) +
guides(color = FALSE) +
theme_ts()
stock_status <-
ecodata::stock_status %>%
mutate(Code = recode(Code, "Dogfish" = "Sp. Dogfish" )) %>%
spread(.,Var,Value) %>%
filter(Council %in% c("MAFMC","Both")) %>%
group_by(Stock) %>%
mutate(score = case_when(
(B.Bmsy <0.5) ~"a",
(F.Fmsy >1) ~ "a",
(F.Fmsy < 1 & B.Bmsy > 0.5 & B.Bmsy < 1) ~ "b",
(F.Fmsy < 1 & B.Bmsy > 1) ~ "c"))
#Plot constants
y.max <- 2.0 #1.75 mackerel cut off F/Fmsy is 1.8
x.max <- 2.6
#A dataframe that defines custom legend for stocks with unknown status
# unknown <- data.frame(text = c("Unknown Status", "Longfin Squid",
# "Shortfin Squid", "N. Goosefish", "S. Goosefish"),
# x = rep(0.9*x.max,5), y = seq(0.93*y.max,1.4,-.1))
# Custom Color
custom_color<- c("#56B4E9", "#009E73", "#0072B2")
#Plotting code
ggplot(data = stock_status) +
geom_vline(xintercept = 1, linetype = "dotted")+
geom_vline(xintercept = 0.5, linetype = "dashed")+
geom_hline(yintercept = 1, linetype = "dashed") +
geom_point(aes(x = B.Bmsy,
y = F.Fmsy,
shape = Council,
color = score)) +
geom_text_repel(aes(x = B.Bmsy, #geom_text_repel auto-jitters text around points
y = F.Fmsy,
label = Code,
color = score),
show.legend = FALSE, nudge_y = -0.01, nudge_x = 0.05) +
scale_color_brewer(palette = "Dark2",
breaks = stock_status$score) +
ylim(0,y.max) +
xlim(0,x.max) +
# geom_text(data = unknown, aes(x = x, y = y, label = text), #Custom legend for unknown stock status
# size = c(4.75,rep(4,4))) +
# annotate("rect", xmin = 0.8*x.max,
# xmax = x.max,
# ymin = 0.65*y.max,
# ymax = 0.90*y.max,
# alpha = 0.1) +
xlab(expression(~B/B[msy])) +
ylab(expression(~F/F[msy])) +
guides(color = FALSE) +
theme_ts()
stock_status <- stock_status_stockSMART %>%
mutate(Code = recode(Code, "Dogfish" = "Sp. Dogfish" )) %>%
spread(.,Var,Value) %>%
filter(Council %in% c("NEFMC","Both")) %>%
group_by(Stock) %>%
mutate(score = case_when(
(B.Bmsy <0.5) ~"a",
(F.Fmsy >1) ~ "a",
(F.Fmsy < 1 & B.Bmsy > 0.5 & B.Bmsy < 1) ~ "b",
(F.Fmsy < 1 & B.Bmsy > 1) ~ "c"))
#Plot constants
y.max <- 1.5
x.max <- 10
all_missing <- stock_status %>%
filter(is.na(B.Bmsy),is.na(F.Fmsy)) %>%
dplyr::select(Code, Council)
b_missing <- stock_status %>%
filter(is.na(B.Bmsy), !is.na(F.Fmsy)) %>%
dplyr::select(Code, Council)
f_missing <- stock_status %>%
filter(is.na(F.Fmsy), !is.na(B.Bmsy)) %>%
dplyr::select(Code, Council)
#A dataframe that defines custom legend for stocks with unknown status
# all.df <- data.frame(text = all_missing$Code,
# x = rep(x.max*0.9,length(all_missing$Code)),
# #y = seq(1.45,1.05, length.out = 7))
# y = seq(1.45,1.05, length.out = length(all_missing$Code)))
# b.df <- data.frame(text = b_missing$Code,
# x = rep(x.max*0.7,length(b_missing$Code)),
# y = c(1.45,2.15, length.out = length(b_missing$Code)))
# f.df <- data.frame(text = f_missing$Code,
# x = rep(x.max*0.5,length(f_missing$Code)),
# y = seq(1.45,1.0, length.out = length(f_missing$Code)))
# Custom Color
custom_color<- c("#56B4E9", "#009E73", "#0072B2")
#Plotting code
ggplot(data = stock_status) +
geom_vline(xintercept = 1, linetype = "dotted", color = "grey60")+
geom_vline(xintercept = 0.5, linetype = "dashed", color = "grey60")+
geom_hline(yintercept = 1, linetype = "dashed", color = "grey60") +
geom_point(aes(x = B.Bmsy,
y = F.Fmsy,
color = stock_status$score)) +
geom_text_repel(aes(x = B.Bmsy, #geom_text_repel auto-jitters text around points
y = F.Fmsy,
label = Code,
color = stock_status$score), show.legend = FALSE,nudge_y = -0.01, nudge_x = 0.05) +
ylim(0,y.max) +
xlim(0,x.max*1.1) +
# geom_text(data = all.df, aes(x = x, y = y, label = text),show.legend = FALSE, size = 3)+
# geom_text(data = b.df, aes(x = x, y = y, label = text),show.legend = FALSE, size = 3)+
# geom_text(data = f.df, aes(x = x, y = y, label = text),show.legend = FALSE, size = 3)+
# scale_color_brewer(palette = "Dark2", #Change legend labels for clarity
# breaks = stock_status$score) +
# annotate("rect", xmin = 0.924*x.max,
# xmax = 1.08*x.max,
# ymin = 0.645*y.max,
# ymax = 0.98*y.max,
# alpha = 0.01) +
# annotate("text", x = 9, y = 1.5, label = "F and B missing", fontface =2, size = 3)+
# annotate("rect",
# xmin = 0.70*x.max,
# xmax = 0.85*x.max,
# ymin = 0.90*y.max,
# ymax = 1.8,
# alpha = 0.01) +
# annotate("text", x = 7, y = 1.5, label = "B missing", fontface =2, size = 3)+
# annotate("rect", xmin = 0.509*x.max,
# xmax = 0.681*x.max,
# ymin = 0.65*y.max,
# ymax = 0.98*y.max,
# alpha = 0.01) +
# annotate("text", x = 5, y = 1.5, label = "F missing", fontface =2, size = 3)+
xlab(expression(~B/B[msy])) +
ylab(expression(~F/F[msy])) +
guides(color = FALSE) +
theme_ts()
stock_status <- ecodata::stock_status %>%
mutate(Code = recode(Code, "Dogfish" = "Sp. Dogfish" )) %>%
spread(.,Var,Value) %>%
filter(Council %in% c("NEFMC","Both")) %>%
group_by(Stock) %>%
mutate(score = case_when(
(B.Bmsy <0.5) ~"a",
(F.Fmsy >1) ~ "a",
(F.Fmsy < 1 & B.Bmsy > 0.5 & B.Bmsy < 1) ~ "b",
(F.Fmsy < 1 & B.Bmsy > 1) ~ "c"))
#Plot constants
y.max <- 1.5
x.max <- 10
all_missing <- stock_status %>%
filter(is.na(B.Bmsy),is.na(F.Fmsy)) %>%
dplyr::select(Code, Council)
b_missing <- stock_status %>%
filter(is.na(B.Bmsy), !is.na(F.Fmsy)) %>%
dplyr::select(Code, Council)
f_missing <- stock_status %>%
filter(is.na(F.Fmsy), !is.na(B.Bmsy)) %>%
dplyr::select(Code, Council)
#A dataframe that defines custom legend for stocks with unknown status
# all.df <- data.frame(text = all_missing$Code,
# x = rep(x.max*0.9,length(all_missing$Code)),
# y = seq(1.45,1.05, length.out = length(all_missing$Code)))
# b.df <- data.frame(text = b_missing$Code,
# x = rep(x.max*0.7,length(b_missing$Code)),
# y = c(1.45,2.15, length.out = length(b_missing$Code)))
# f.df <- data.frame(text = f_missing$Code,
# x = rep(x.max*0.5,length(f_missing$Code)),
# y = seq(1.45,1.0, length.out = length(f_missing$Code)))
# Custom Color
custom_color<- c("#56B4E9", "#009E73", "#0072B2")
#Plotting code
ggplot(data = stock_status) +
geom_vline(xintercept = 1, linetype = "dotted", color = "grey60")+
geom_vline(xintercept = 0.5, linetype = "dashed", color = "grey60")+
geom_hline(yintercept = 1, linetype = "dashed", color = "grey60") +
geom_point(aes(x = B.Bmsy,
y = F.Fmsy,
color = stock_status$score)) +
geom_text_repel(aes(x = B.Bmsy, #geom_text_repel auto-jitters text around points
y = F.Fmsy,
label = Code,
color = stock_status$score), show.legend = FALSE,nudge_y = -0.01, nudge_x = 0.05) +
ylim(0,y.max) +
xlim(0,x.max*1.1) +
# geom_text(data = all.df, aes(x = x, y = y, label = text),show.legend = FALSE, size = 3)+
# geom_text(data = b.df, aes(x = x, y = y, label = text),show.legend = FALSE, size = 3)+
# geom_text(data = f.df, aes(x = x, y = y, label = text),show.legend = FALSE, size = 3)+
# scale_color_brewer(palette = "Dark2", #Change legend labels for clarity
# breaks = stock_status$score) +
# annotate("rect", xmin = 0.924*x.max,
# xmax = 1.08*x.max,
# ymin = 0.645*y.max,
# ymax = 0.98*y.max,
# alpha = 0.01) +
# annotate("text", x = 9, y = 1.5, label = "F and B missing", fontface =2, size = 3)+
# annotate("rect",
# xmin = 0.70*x.max,
# xmax = 0.85*x.max,
# ymin = 0.90*y.max,
# ymax = 1.8,
# alpha = 0.01) +
# annotate("text", x = 7, y = 1.5, label = "B missing", fontface =2, size = 3)+
# annotate("rect", xmin = 0.509*x.max,
# xmax = 0.681*x.max,
# ymin = 0.65*y.max,
# ymax = 0.98*y.max,
# alpha = 0.01) +
# annotate("text", x = 5, y = 1.5, label = "F missing", fontface =2, size = 3)+
xlab(expression(~B/B[msy])) +
ylab(expression(~F/F[msy])) +
guides(color = FALSE) +
theme_ts()
MAFMC looks reasonable based on 2021 updates to assessments.
NEFMC may a problem; silver hake stocks look better in 2021 than 2020. No update on the stock assessment report site but maybe hake assessments don’t appear there?
Both hakes were assessed in 2020. The 2020 S Silver Hake assessment shows them as not overfished. So the updated stocksmart info looks correct.
There was an error in the entity name field in the preliminary stocksmart dataset that caused S Silver Hake 2020 assessment results to not merge properly… we were showing 2017 in the previous version of ecodata. The new stocksmart data is correct for silver hake.
N Windowpane appears because I didn’t erase he Fmsy info in stocksmart as the previous ecodata get_stocks() function does. This may be appropriate; it did not appear in the 2020 plot but I don’t remember why. Need to recheck.
Leave all current stocksmart data in the 2021assess.csv and submit it. Ask for review by PDB prior to publishing.
Used the form here: https://apps-nefsc.fisheries.noaa.gov/saw/sasi/sasi_report_options.php
Files should be up-to-date as of the day of my query, November 16, 2021, according to the website.
Checked the boxes: Year–2021
Species with 2021 updates: Bluefish, Atlantic cod, Atlantic mackerel, Black sea bass, Golden tilefish, Scup, Summer flounder.
The only ones that have stock status are Mid-Atlantic species and they look like reasonable changes.
I think we should be able to summarize catches from stocksmart::stockAssessmentData
by RegionalEcosystem:
Northeast Shelf, Alaska Ecosystem Complex, Atlantic Highly Migratory, Pacific Highly Migratory, Pacific Islands Ecosystem Complex, California Current, Gulf of Mexico, Southeast Shelf, Southeast Shelf / Gulf of Mexico, California Current / Alaska Ecosystem Complex, Caribbean Sea, NA
But the issue is converting to common units before summing.
NEcatch <- stocksmart::stockAssessmentData %>%
filter(RegionalEcosystem == "Northeast Shelf",
Metric == "Catch") %>%
group_by(StockName) %>%
filter(AssessmentYear == max(AssessmentYear)) %>%
ungroup() %>%
mutate(Catchmt = case_when(Units == "Thousand Metric Tons" ~ Value*1000,
TRUE ~ Value))
p <- ggplot(NEcatch, aes(x=Year, y=Catchmt, fill = StockName)) +
#geom_bar(stat="identity") +
geom_bar_interactive(width = 0.95, stat = "identity", show.legend = FALSE,
aes(tooltip = StockName, data_id = StockName))
theme(legend.position = "none")
## List of 1
## $ legend.position: chr "none"
## - attr(*, "class")= chr [1:2] "theme" "gg"
## - attr(*, "complete")= logi FALSE
## - attr(*, "validate")= logi TRUE
ggiraph(code=print(p))
NEcatchtt <- NEcatch %>%
filter(Units=="Thousand Metric Tons")
Units of Catch
in the Northeast Shelf regional ecosystem, most recent assessments only:
Metric Tons, Thousand Metric Tons
Which species have catch in thousands of metric tons:
Ocean pout - Northwestern Atlantic Coast, Windowpane - Southern New England / Mid-Atlantic
These were converted to tons in the plot above.