Skip to content

Commit 695a53d

Browse files
author
Stephanie Owen
committed
script to produce commerical indicators
1 parent ca6778f commit 695a53d

7 files changed

Lines changed: 662 additions & 50 deletions

File tree

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
## Commercial ESP indicators Script
2+
## translated from Stata code 2/24/2026
3+
## Owner: Samantha Werner
4+
5+
#overview-- This code creates six economic commercial fishing indicators used in ESP work.
6+
# The code below pulls data, deflates any monetary values and formats data to what is needed for the time series plots.
7+
8+
#Indicators created: Commercial Landings (LBS): The total weight of the species landed (e.g., Commercial_LONGFINSQUID_Landings_LBS).
9+
10+
#Number of Commercial Vessels: The count of unique permits landing that species (e.g., N_Commercial_Vessels_Landing_LONGFINSQUID).
11+
#Average Price per Pound: The average annual price, winsorized to handle outliers and adjusted for inflation (e.g., AVGPRICE_LONGFINSQUID_2024_DOLlb).
12+
#Total Annual Revenue: The total value of all landings for that species, adjusted for inflation (e.g., TOTALANNUALREV_LONGFINSQUID_2024Dols).
13+
#Average Revenue per Vessel: The average revenue earned per permit per year, adjusted for inflation (e.g., AVGVESREVperYr_LONGFINSQUID_2024_DOLlb).
14+
#Average Annual Diesel Price: The price of Ultra-Low-Sulfur No. 2 Diesel (from FRED), adjusted for inflation (e.g., AVGANNUAL_DIESEL_PRICE2024dols).
15+
16+
## This uses CFDERS data but may need to be updated to CAMs
17+
18+
19+
20+
#######################Running the code steps##########################
21+
#1. Change top of the code to update:
22+
# - Oracle log in information
23+
# - The time series you want
24+
# - The species (nespp3) and how you want your species to be named within the end file (sppname)
25+
# - the year you want to deflate to
26+
27+
## before running!!!#
28+
# - make sure you are connected to VPN
29+
#-- ensure all packages are installed
30+
# -- you followed the steps above
31+
#-- you have a folder in your directory called "data"
32+
33+
34+
#install.packages("ROracle")
35+
#install.packages("DescTools")
36+
37+
library(ROracle)
38+
library(DBI)
39+
library(fredr)
40+
library(tidyverse)
41+
library(DescTools) # For Winsorize
42+
43+
######################################################################
44+
############################update code below to match the years, species and user information#############
45+
#####################################################################
46+
47+
# 1. Setup Credentials
48+
ora_id <- "INSERT USERNAME HERE"
49+
oraprod_pw <- "INSERT PASSWORD HERE"
50+
51+
spp_name <- "LONGFINSQUID" # Replace with your actual species name
52+
nespp3_codes <- "('801')" # Note the single quotes inside the string for SQL
53+
54+
START.YEAR <- 1996
55+
END.YEAR <- 2025
56+
57+
## set year you would like to deflate to
58+
deflate_yr <- 2025
59+
60+
# This looks for a folder named 'data' then 'intermediate' inside your current directory
61+
data_intermediate <- file.path("data/intermediate")
62+
63+
# Set your API key for FRED data (deflation) you may need to log into FRED API Keys and request a new one. https://fred.stlouisfed.org/docs/api/api_key.html
64+
fredr_set_key("a09e5d083681605146191f4996992c6e")
65+
66+
#################################################################
67+
##no editiing should be needed past this point
68+
#####################################################
69+
# 2. Build the connection string
70+
shost <- "nefsc-prod-01-db.nmfs.noaa.gov"
71+
port <- 1521
72+
ssid <- "NEFSC_DB_PROD.nefscproddbsn.nefscprodvcn.oraclevcn.com"
73+
74+
# Using the name consistent with your loop
75+
nefscusers.connect.string <- paste0(
76+
"(DESCRIPTION=",
77+
"(ADDRESS=(PROTOCOL=tcp)(HOST=", shost, ")(PORT=", port, "))",
78+
"(CONNECT_DATA=(SERVICE_NAME=", ssid, ")))"
79+
)
80+
81+
# 3. Connect ONCE outside the loop
82+
drv <- dbDriver("Oracle")
83+
conn <- dbConnect(drv, ora_id, password = oraprod_pw, dbname = nefscusers.connect.string)
84+
85+
##### 4. Price deflator
86+
87+
gdp_deflator <- fredr(
88+
series_id = "GDPDEF",
89+
observation_start = as.Date(paste0(START.YEAR, "-01-01")),
90+
observation_end = as.Date(paste0(END.YEAR, "-12-31")),
91+
frequency = "a" # Annual
92+
) %>%
93+
mutate(YEAR = as.numeric(format(date, "%Y"))) %>%
94+
select(YEAR, GDPDEF = value)
95+
96+
97+
# 1. Build the query string using your R variables
98+
# We use paste0 to insert the species name into the column alias
99+
# and the codes into the WHERE clause.
100+
query_landings <- paste0(
101+
"SELECT YEAR, SUM(SPPLNDLB) AS total_", spp_name,
102+
" FROM NEFSC_GARFO.CFDERS_ALL_YEARS ",
103+
" WHERE NESPP3 IN ", nespp3_codes,
104+
"AND YEAR BETWEEN ", START.YEAR, " AND ", END.YEAR,
105+
" GROUP BY YEAR ORDER BY YEAR"
106+
)
107+
108+
# 2. Execute the query
109+
landings_data <- dbGetQuery(conn, query_landings)
110+
111+
# 3. View the result
112+
print(head(landings_data))
113+
114+
115+
# Standardize the data frame to match the required indicator format
116+
landings_final <- landings_data %>%
117+
mutate(
118+
CATEGORY = "Commercial",
119+
INDICATOR_NAME = paste0("Commercial_", spp_name, "_Landings_LBS"),
120+
SIGN = "N/A",
121+
INDICATOR_TYPE = "Socioeconomic"
122+
) %>%
123+
# Rename the sum column to DATA_VALUE (Equivalent to Stata rename)
124+
rename(DATA_VALUE = !!paste0("TOTAL_", spp_name)) %>%
125+
select(YEAR, DATA_VALUE, CATEGORY, INDICATOR_NAME, SIGN, INDICATOR_TYPE)
126+
127+
#
128+
129+
######################### n vessels pull #############
130+
131+
# 1. Build the query string
132+
# I simplified the alias to N_VESSELS so the rename() below actually works.
133+
# I also added a space before 'FROM' to prevent syntax errors.
134+
query_Nvessels <- paste0(
135+
"SELECT YEAR, count(distinct PERMIT) AS N_VESSELS ",
136+
"FROM NEFSC_GARFO.CFDERS_ALL_YEARS ",
137+
"WHERE NESPP3 IN ", nespp3_codes,
138+
" AND YEAR BETWEEN ", START.YEAR, " AND ", END.YEAR,
139+
" GROUP BY YEAR ORDER BY YEAR"
140+
)
141+
142+
# 2. Execute the query
143+
Nvessels_data <- dbGetQuery(conn, query_Nvessels)
144+
145+
# 3. Format to match Stata indicators
146+
Nvessels_final <- Nvessels_data %>%
147+
mutate(
148+
CATEGORY = "Commercial",
149+
# This creates the long name you want in the final table
150+
INDICATOR_NAME = paste0("N_Commercial_Vessels_Landing_", spp_name),
151+
SIGN = "N/A",
152+
INDICATOR_TYPE = "Socioeconomic"
153+
) %>%
154+
# Now this rename will work because the SQL alias matches 'N_VESSELS'
155+
# Note: Oracle often returns names in UPPERCASE, so we check for both.
156+
rename(DATA_VALUE = any_of(c("N_VESSELS", "N_vessels"))) %>%
157+
select(YEAR, DATA_VALUE, CATEGORY, INDICATOR_NAME, SIGN, INDICATOR_TYPE)
158+
159+
# 4. View the result
160+
print(head(Nvessels_final))
161+
162+
##################average prices##################
163+
164+
#1. Pull Price Data from Oracle ---
165+
# Uses the 'conn' object you already established
166+
query_price <- paste0(
167+
"SELECT SPPVALUE, SPPLNDLB, YEAR FROM NEFSC_GARFO.CFDERS_ALL_YEARS ",
168+
"WHERE NESPP3 IN ", nespp3_codes,
169+
" AND YEAR BETWEEN ", START.YEAR, " AND ", END.YEAR
170+
)
171+
172+
price_raw <- dbGetQuery(conn, query_price)
173+
174+
#--- 2. Calculate Average Annual Prices (Manual Winsorize) ---
175+
price_annual <- price_raw %>%
176+
mutate(price_lb = SPPVALUE / SPPLNDLB) %>%
177+
# Remove Infinity or NA if pounds were 0
178+
filter(is.finite(price_lb)) %>%
179+
group_by(YEAR) %>%
180+
mutate(
181+
# Calculate the 1st and 99th percentiles for this year
182+
p01 = quantile(price_lb, 0.01, na.rm = TRUE),
183+
p99 = quantile(price_lb, 0.99, na.rm = TRUE),
184+
# "Squish" values outside that range (This is Winsorizing!)
185+
price_lb_w = case_when(
186+
price_lb < p01 ~ p01,
187+
price_lb > p99 ~ p99,
188+
TRUE ~ price_lb
189+
)
190+
) %>%
191+
summarise(AVG_NOMINAL_PRICE = mean(price_lb_w, na.rm = TRUE)) %>%
192+
ungroup()
193+
194+
# --- 3. Adjust for Inflation (Deflate) ---
195+
# (Keep this the same as before)
196+
197+
base_index_val <- gdp_deflator$GDPDEF[gdp_deflator$YEAR == deflate_yr]
198+
199+
price_final <- price_annual %>%
200+
left_join(gdp_deflator, by = "YEAR") %>%
201+
mutate(
202+
DATA_VALUE = (AVG_NOMINAL_PRICE / GDPDEF) * base_index_val,
203+
CATEGORY = "Commercial",
204+
INDICATOR_NAME = paste0("AVGPRICE_", spp_name, "_", deflate_yr, "_DOLlb"),
205+
SIGN = "N/A",
206+
INDICATOR_TYPE = "Socioeconomic"
207+
) %>%
208+
select(YEAR, DATA_VALUE, CATEGORY, INDICATOR_NAME, SIGN, INDICATOR_TYPE)
209+
210+
# --- 4. Cleanup ---
211+
212+
213+
print(price_final)
214+
215+
216+
##To ensure all indicators respect your START.YEAR and END.YEAR variables, I have integrated those filters into both the SQL queries (for database pulls) and the fredr calls (for external diesel data).
217+
218+
219+
220+
221+
################## Total Annual Revenues ##################
222+
223+
# 1. Pull Revenue Data
224+
query_revs <- paste0(
225+
"SELECT YEAR, SUM(SPPVALUE) AS TOTAL_REV ",
226+
"FROM NEFSC_GARFO.CFDERS_ALL_YEARS ",
227+
"WHERE NESPP3 IN ", nespp3_codes,
228+
" AND YEAR BETWEEN ", START.YEAR, " AND ", END.YEAR,
229+
" GROUP BY YEAR ORDER BY YEAR"
230+
)
231+
revs_raw <- dbGetQuery(conn, query_revs)
232+
233+
# 2. Deflate and Format
234+
revs_final <- revs_raw %>%
235+
left_join(gdp_deflator, by = "YEAR") %>%
236+
mutate(
237+
DATA_VALUE = (TOTAL_REV / GDPDEF) * base_index_val,
238+
CATEGORY = "Commercial",
239+
INDICATOR_NAME = paste0("TOTALANNUALREV_", spp_name, "_", deflate_yr, "Dols"),
240+
SIGN = "N/A",
241+
INDICATOR_TYPE = "Socioeconomic"
242+
) %>%
243+
select(YEAR, DATA_VALUE, CATEGORY, INDICATOR_NAME, SIGN, INDICATOR_TYPE)
244+
245+
################## Fuel Prices ##################
246+
247+
# 1. Pull Diesel Price from FRED with Year Range
248+
fuel_raw <- fredr(
249+
series_id = "DDFUELNYH",
250+
observation_start = as.Date(paste0(START.YEAR, "-01-01")),
251+
observation_end = as.Date(paste0(END.YEAR, "-12-31")),
252+
frequency = "a"
253+
) %>%
254+
mutate(YEAR = as.numeric(format(date, "%Y"))) %>%
255+
# Stata 'drop if missing(DDFUELNYH)' equivalent:
256+
filter(!is.na(value)) %>%
257+
select(YEAR, DDFUELNYH = value)
258+
259+
# 2. Deflate and Format
260+
fuel_final <- fuel_raw %>%
261+
left_join(gdp_deflator, by = "YEAR") %>%
262+
mutate(
263+
DATA_VALUE = (DDFUELNYH / GDPDEF) * base_index_val,
264+
CATEGORY = "Commercial",
265+
INDICATOR_NAME = paste0("AVGANNUAL_DIESEL_PRICE", deflate_yr, "dols"),
266+
SIGN = "N/A",
267+
INDICATOR_TYPE = "Socioeconomic"
268+
) %>%
269+
select(YEAR, DATA_VALUE, CATEGORY, INDICATOR_NAME, SIGN, INDICATOR_TYPE)
270+
271+
############ Average Revenue Per Vessel ##################
272+
273+
# 1. Pull Revenue per Permit/Year with Year Range
274+
query_ves_rev <- paste0(
275+
"SELECT YEAR, PERMIT, SUM(SPPVALUE) AS VESSEL_TOTAL_REV ",
276+
"FROM NEFSC_GARFO.CFDERS_ALL_YEARS ",
277+
"WHERE NESPP3 IN ", nespp3_codes,
278+
" AND YEAR BETWEEN ", START.YEAR, " AND ", END.YEAR,
279+
" GROUP BY YEAR, PERMIT"
280+
)
281+
ves_rev_raw <- dbGetQuery(conn, query_ves_rev)
282+
283+
# 2. Calculate Mean per Year and Deflate
284+
av_ves_rev_final <- ves_rev_raw %>%
285+
group_by(YEAR) %>%
286+
summarise(AVG_VESSEL_REV = mean(VESSEL_TOTAL_REV, na.rm = TRUE)) %>%
287+
left_join(gdp_deflator, by = "YEAR") %>%
288+
mutate(
289+
DATA_VALUE = (AVG_VESSEL_REV / GDPDEF) * base_index_val,
290+
CATEGORY = "Commercial",
291+
INDICATOR_NAME = paste0("AVGVESREVperYr_", spp_name, "_", deflate_yr, "_DOLlb"),
292+
SIGN = "N/A",
293+
INDICATOR_TYPE = "Socioeconomic"
294+
) %>%
295+
select(YEAR, DATA_VALUE, CATEGORY, INDICATOR_NAME, SIGN, INDICATOR_TYPE)
296+
297+
##disconnect from oracle
298+
dbDisconnect(conn)
299+
################## MASTER APPEND ##################
300+
301+
# 1. Create a list of all your final data frames
302+
# This acts like a 'stack' of all the indicators you just created
303+
indicator_list <- list(
304+
landings_final,
305+
Nvessels_final,
306+
price_final,
307+
revs_final,
308+
fuel_final,
309+
av_ves_rev_final
310+
)
311+
312+
# 2. Use bind_rows to stack them into one long file
313+
# This is identical to running 'append' multiple times in Stata
314+
final_master_file <- bind_rows(indicator_list)
315+
316+
# 3. Final Quality Check (Filtering by your start/end years)
317+
final_master_file <- final_master_file %>%
318+
filter(YEAR >= START.YEAR & YEAR <= END.YEAR) %>%
319+
arrange(INDICATOR_NAME, YEAR)
320+
321+
# 4. Save the file (Equivalent to Stata's 'save ..., replace')
322+
# Use file.path to make sure the folder and filename are joined correctly
323+
write.csv(
324+
final_master_file,
325+
file = file.path(data_intermediate, paste0(spp_name, "_Commercial_Indicators_Master.csv")),
326+
row.names = FALSE
327+
)
328+
329+
# 5. View a summary of what you appended
330+
print(table(final_master_file$INDICATOR_NAME))
331+
332+
333+
334+
335+
336+

0 commit comments

Comments
 (0)