knitr::opts_chunk$set(echo = TRUE)
library(readxl)
## Warning: package 'readxl' was built under R version 4.5.3
library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.0, PROJ 9.6.0; sf_use_s2() is TRUE
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.5.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.5.3
library(viridis)
## Loading required package: viridisLite
library(geodata)
## Warning: package 'geodata' was built under R version 4.5.3
## Loading required package: terra
## Warning: package 'terra' was built under R version 4.5.3
## terra 1.9.34
# =========================================================
# USDA 2022 CATTLE PRODUCTION MAP
# =========================================================

# Load USDA livestock data
livestock <- read_excel(
  "data.xlsx",
  sheet = "Livestock and Animals"
)

# Load county-name lookup
county_names <- read_excel(
  "data.xlsx",
  sheet = "County Names"
)

# ---------------------------------------------------------
# California county boundaries
# ---------------------------------------------------------

us_counties <- geodata::gadm(
  country = "USA",
  level = 2,
  path = "data"
)

california <- st_as_sf(us_counties)

california <- california[
  california$NAME_1 == "California",
]

# ---------------------------------------------------------
# Find the county-name and FIPS columns
# ---------------------------------------------------------

fips_column <- names(county_names)[
  grepl("fips", names(county_names), ignore.case = TRUE)
][1]

name_column <- names(county_names)[
  grepl("county|name", names(county_names), ignore.case = TRUE)
][1]

# Create clean lookup table
county_lookup <- county_names %>%
  select(
    FIPS = all_of(fips_column),
    County = all_of(name_column)
  ) %>%
  mutate(
    FIPS = as.character(FIPS),
    FIPS = gsub("\\D", "", FIPS),
    FIPS = sprintf("%05d", as.numeric(FIPS)),
    County = trimws(County),
    County = gsub(
      "\\s+County$",
      "",
      County,
      ignore.case = TRUE
    )
  ) %>%
  distinct(FIPS, .keep_all = TRUE)

# ---------------------------------------------------------
# Extract 2022 cow/heifer inventory
# ---------------------------------------------------------

cattle_2022 <- livestock %>%
  mutate(
    FIPS = as.character(FIPSTEXT),
    FIPS = gsub("\\D", "", FIPS),
    FIPS = sprintf("%05d", as.numeric(FIPS))
  ) %>%
  select(
    FIPS,
    cattle = y22_M099_valueNumeric
  ) %>%
  left_join(
    county_lookup,
    by = "FIPS"
  ) %>%
  filter(
    !is.na(County),
    substr(FIPS, 1, 2) == "06"
  ) %>%
  select(
    County,
    cattle
  )

# ---------------------------------------------------------
# Join cattle data to California counties
# ---------------------------------------------------------

cattle_map <- california %>%
  left_join(
    cattle_2022,
    by = c("NAME_2" = "County")
  )

# ---------------------------------------------------------
# Check data match
# ---------------------------------------------------------

print(
  cattle_map %>%
    st_drop_geometry() %>%
    summarise(
      total_counties = n(),
      counties_with_data = sum(!is.na(cattle)),
      counties_without_data = sum(is.na(cattle))
    )
)
##   total_counties counties_with_data counties_without_data
## 1             58                 55                     3
# ---------------------------------------------------------
# Create dark California cattle map
# ---------------------------------------------------------

ggplot(cattle_map) +

  geom_sf(
    aes(fill = cattle),
    color = "#34383A",
    linewidth = 0.25
  ) +

  scale_fill_viridis_c(
    option = "magma",
    trans = "sqrt",
    na.value = "#151819",
    name = "Cows & heifers\ninventory"
  ) +

  labs(
    title = "Where Cattle Production Is Concentrated",
    subtitle = "Cows and heifers that had calved — California, 2022",
    caption = "Source: USDA National Agricultural Statistics Service, 2022 Census of Agriculture."
  ) +

  theme_void() +

  theme(
    plot.background = element_rect(
      fill = "#0B0D0E",
      color = NA
    ),

    panel.background = element_rect(
      fill = "#0B0D0E",
      color = NA
    ),

    plot.title = element_text(
      color = "#F2EFE9",
      size = 21,
      face = "bold"
    ),

    plot.subtitle = element_text(
      color = "#8E9294",
      size = 11
    ),

    plot.caption = element_text(
      color = "#6F7477",
      size = 8,
      hjust = 0
    ),

    legend.background = element_rect(
      fill = "#0B0D0E",
      color = NA
    ),

    legend.text = element_text(
      color = "#E8E5DF"
    ),

    legend.title = element_text(
      color = "#E8E5DF",
      face = "bold"
    )
  )

library(readxl)

farms <- read_excel(
  "data.xlsx",
  sheet = "Farms"
)

economics <- read_excel(
  "data.xlsx",
  sheet = "Economics"
)

producers <- read_excel(
  "data.xlsx",
  sheet = "Producers"
)

cat("FARMS:\n")
## FARMS:
print(names(farms))
##  [1] "FIPS"                  "FIPSTEXT"              "y22_M001_valueNumeric"
##  [4] "y22_M001_valueText"    "y22_M001_classRange"   "y22_M002_valueNumeric"
##  [7] "y22_M002_valueText"    "y22_M002_classRange"   "y22_M050_valueNumeric"
## [10] "y22_M050_valueText"    "y22_M050_classRange"   "y22_M051_valueNumeric"
## [13] "y22_M051_valueText"    "y22_M051_classRange"   "y22_M052_valueNumeric"
## [16] "y22_M052_valueText"    "y22_M052_classRange"   "y22_M053_valueNumeric"
## [19] "y22_M053_valueText"    "y22_M053_classRange"   "y22_M054_valueNumeric"
## [22] "y22_M054_valueText"    "y22_M054_classRange"   "y22_M055_valueNumeric"
## [25] "y22_M055_valueText"    "y22_M055_classRange"   "y22_M056_valueNumeric"
## [28] "y22_M056_valueText"    "y22_M056_classRange"   "y22_M057_valueNumeric"
## [31] "y22_M057_valueText"    "y22_M057_classRange"   "y22_M058_valueNumeric"
## [34] "y22_M058_valueText"    "y22_M058_classRange"   "y22_M059_valueNumeric"
## [37] "y22_M059_valueText"    "y22_M059_classRange"   "y22_M064_valueNumeric"
## [40] "y22_M064_valueText"    "y22_M064_classRange"   "y22_M065_valueNumeric"
## [43] "y22_M065_valueText"    "y22_M065_classRange"   "y22_M066_valueNumeric"
## [46] "y22_M066_valueText"    "y22_M066_classRange"   "y22_M067_valueNumeric"
## [49] "y22_M067_valueText"    "y22_M067_classRange"   "y22_M068_valueNumeric"
## [52] "y22_M068_valueText"    "y22_M068_classRange"   "y22_M069_valueNumeric"
## [55] "y22_M069_valueText"    "y22_M069_classRange"   "y22_M070_valueNumeric"
## [58] "y22_M070_valueText"    "y22_M070_classRange"   "y22_M071_valueNumeric"
## [61] "y22_M071_valueText"    "y22_M071_classRange"   "y22_M079_valueNumeric"
## [64] "y22_M079_valueText"    "y22_M079_classRange"   "y22_M080_valueNumeric"
## [67] "y22_M080_valueText"    "y22_M080_classRange"   "y22_M081_valueNumeric"
## [70] "y22_M081_valueText"    "y22_M081_classRange"   "y22_M174_valueNumeric"
## [73] "y22_M174_valueText"    "y22_M174_classRange"
cat("\nECONOMICS:\n")
## 
## ECONOMICS:
print(names(economics))
##   [1] "FIPS"                  "FIPSTEXT"              "y22_M003_valueNumeric"
##   [4] "y22_M003_valueText"    "y22_M003_classRange"   "y22_M004_valueNumeric"
##   [7] "y22_M004_valueText"    "y22_M004_classRange"   "y22_M005_valueNumeric"
##  [10] "y22_M005_valueText"    "y22_M005_classRange"   "y22_M006_valueNumeric"
##  [13] "y22_M006_valueText"    "y22_M006_classRange"   "y22_M007_valueNumeric"
##  [16] "y22_M007_valueText"    "y22_M007_classRange"   "y22_M008_valueNumeric"
##  [19] "y22_M008_valueText"    "y22_M008_classRange"   "y22_M009_valueNumeric"
##  [22] "y22_M009_valueText"    "y22_M009_classRange"   "y22_M010_valueNumeric"
##  [25] "y22_M010_valueText"    "y22_M010_classRange"   "y22_M011_valueNumeric"
##  [28] "y22_M011_valueText"    "y22_M011_classRange"   "y22_M012_valueNumeric"
##  [31] "y22_M012_valueText"    "y22_M012_classRange"   "y22_M013_valueNumeric"
##  [34] "y22_M013_valueText"    "y22_M013_classRange"   "y22_M014_valueNumeric"
##  [37] "y22_M014_valueText"    "y22_M014_classRange"   "y22_M015_valueNumeric"
##  [40] "y22_M015_valueText"    "y22_M015_classRange"   "y22_M016_valueNumeric"
##  [43] "y22_M016_valueText"    "y22_M016_classRange"   "y22_M017_valueNumeric"
##  [46] "y22_M017_valueText"    "y22_M017_classRange"   "y22_M018_valueNumeric"
##  [49] "y22_M018_valueText"    "y22_M018_classRange"   "y22_M019_valueNumeric"
##  [52] "y22_M019_valueText"    "y22_M019_classRange"   "y22_M020_valueNumeric"
##  [55] "y22_M020_valueText"    "y22_M020_classRange"   "y22_M021_valueNumeric"
##  [58] "y22_M021_valueText"    "y22_M021_classRange"   "y22_M022_valueNumeric"
##  [61] "y22_M022_valueText"    "y22_M022_classRange"   "y22_M023_valueNumeric"
##  [64] "y22_M023_valueText"    "y22_M023_classRange"   "y22_M024_valueNumeric"
##  [67] "y22_M024_valueText"    "y22_M024_classRange"   "y22_M025_valueNumeric"
##  [70] "y22_M025_valueText"    "y22_M025_classRange"   "y22_M026_valueNumeric"
##  [73] "y22_M026_valueText"    "y22_M026_classRange"   "y22_M027_valueNumeric"
##  [76] "y22_M027_valueText"    "y22_M027_classRange"   "y22_M028_valueNumeric"
##  [79] "y22_M028_valueText"    "y22_M028_classRange"   "y22_M029_valueNumeric"
##  [82] "y22_M029_valueText"    "y22_M029_classRange"   "y22_M030_valueNumeric"
##  [85] "y22_M030_valueText"    "y22_M030_classRange"   "y22_M031_valueNumeric"
##  [88] "y22_M031_valueText"    "y22_M031_classRange"   "y22_M032_valueNumeric"
##  [91] "y22_M032_valueText"    "y22_M032_classRange"   "y22_M033_valueNumeric"
##  [94] "y22_M033_valueText"    "y22_M033_classRange"   "y22_M034_valueNumeric"
##  [97] "y22_M034_valueText"    "y22_M034_classRange"   "y22_M035_valueNumeric"
## [100] "y22_M035_valueText"    "y22_M035_classRange"   "y22_M036_valueNumeric"
## [103] "y22_M036_valueText"    "y22_M036_classRange"   "y22_M037_valueNumeric"
## [106] "y22_M037_valueText"    "y22_M037_classRange"   "y22_M038_valueNumeric"
## [109] "y22_M038_valueText"    "y22_M038_classRange"   "y22_M039_valueNumeric"
## [112] "y22_M039_valueText"    "y22_M039_classRange"   "y22_M040_valueNumeric"
## [115] "y22_M040_valueText"    "y22_M040_classRange"   "y22_M041_valueNumeric"
## [118] "y22_M041_valueText"    "y22_M041_classRange"   "y22_M042_valueNumeric"
## [121] "y22_M042_valueText"    "y22_M042_classRange"   "y22_M043_valueNumeric"
## [124] "y22_M043_valueText"    "y22_M043_classRange"   "y22_M044_valueNumeric"
## [127] "y22_M044_valueText"    "y22_M044_classRange"   "y22_M045_valueNumeric"
## [130] "y22_M045_valueText"    "y22_M045_classRange"   "y22_M046_valueNumeric"
## [133] "y22_M046_valueText"    "y22_M046_classRange"   "y22_M047_valueNumeric"
## [136] "y22_M047_valueText"    "y22_M047_classRange"   "y22_M060_valueNumeric"
## [139] "y22_M060_valueText"    "y22_M060_classRange"   "y22_M061_valueNumeric"
## [142] "y22_M061_valueText"    "y22_M061_classRange"   "y22_M062_valueNumeric"
## [145] "y22_M062_valueText"    "y22_M062_classRange"   "y22_M063_valueNumeric"
## [148] "y22_M063_valueText"    "y22_M063_classRange"   "y22_M175_valueNumeric"
## [151] "y22_M175_valueText"    "y22_M175_classRange"
cat("\nPRODUCERS:\n")
## 
## PRODUCERS:
print(names(producers))
##  [1] "FIPS"                  "FIPSTEXT"              "y22_M048_valueNumeric"
##  [4] "y22_M048_valueText"    "y22_M048_classRange"   "y22_M049_valueNumeric"
##  [7] "y22_M049_valueText"    "y22_M049_classRange"   "y22_M072_valueNumeric"
## [10] "y22_M072_valueText"    "y22_M072_classRange"   "y22_M073_valueNumeric"
## [13] "y22_M073_valueText"    "y22_M073_classRange"   "y22_M074_valueNumeric"
## [16] "y22_M074_valueText"    "y22_M074_classRange"   "y22_M075_valueNumeric"
## [19] "y22_M075_valueText"    "y22_M075_classRange"   "y22_M076_valueNumeric"
## [22] "y22_M076_valueText"    "y22_M076_classRange"   "y22_M077_valueNumeric"
## [25] "y22_M077_valueText"    "y22_M077_classRange"   "y22_M078_valueNumeric"
## [28] "y22_M078_valueText"    "y22_M078_classRange"   "y22_M082_valueNumeric"
## [31] "y22_M082_valueText"    "y22_M082_classRange"   "y22_M083_valueNumeric"
## [34] "y22_M083_valueText"    "y22_M083_classRange"   "y22_M084_valueNumeric"
## [37] "y22_M084_valueText"    "y22_M084_classRange"   "y22_M085_valueNumeric"
## [40] "y22_M085_valueText"    "y22_M085_classRange"   "y22_M086_valueNumeric"
## [43] "y22_M086_valueText"    "y22_M086_classRange"   "y22_M087_valueNumeric"
## [46] "y22_M087_valueText"    "y22_M087_classRange"   "y22_M088_valueNumeric"
## [49] "y22_M088_valueText"    "y22_M088_classRange"   "y22_M089_valueNumeric"
## [52] "y22_M089_valueText"    "y22_M089_classRange"   "y22_M090_valueNumeric"
## [55] "y22_M090_valueText"    "y22_M090_classRange"   "y22_M091_valueNumeric"
## [58] "y22_M091_valueText"    "y22_M091_classRange"   "y22_M092_valueNumeric"
## [61] "y22_M092_valueText"    "y22_M092_classRange"   "y22_M093_valueNumeric"
## [64] "y22_M093_valueText"    "y22_M093_classRange"   "y22_M094_valueNumeric"
## [67] "y22_M094_valueText"    "y22_M094_classRange"   "y22_M095_valueNumeric"
## [70] "y22_M095_valueText"    "y22_M095_classRange"   "y22_M096_valueNumeric"
## [73] "y22_M096_valueText"    "y22_M096_classRange"   "y22_M097_valueNumeric"
## [76] "y22_M097_valueText"    "y22_M097_classRange"
library(readxl)
library(dplyr)
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
# =========================================================
# CALIFORNIA'S LIVESTOCK LANDSCAPE
# USDA 2022 CENSUS OF AGRICULTURE
# =========================================================

# Load livestock data
livestock <- read_excel(
  "data.xlsx",
  sheet = "Livestock and Animals"
)

# Load county-name lookup
county_names <- read_excel(
  "data.xlsx",
  sheet = "County Names"
)

# ---------------------------------------------------------
# Create county lookup
# ---------------------------------------------------------

fips_col <- names(county_names)[
  grepl("fips", names(county_names), ignore.case = TRUE)
][1]

county_col <- names(county_names)[
  grepl("county|name", names(county_names), ignore.case = TRUE)
][1]

county_lookup <- county_names %>%
  select(
    FIPS = all_of(fips_col),
    County = all_of(county_col)
  ) %>%
  mutate(
    FIPS = gsub("\\D", "", as.character(FIPS)),
    FIPS = sprintf("%05d", as.numeric(FIPS)),
    County = trimws(County),
    County = gsub(
      "\\s+County$",
      "",
      County,
      ignore.case = TRUE
    )
  ) %>%
  distinct(FIPS, .keep_all = TRUE)

# ---------------------------------------------------------
# Prepare livestock variables
# ---------------------------------------------------------

livestock_3d <- livestock %>%
  mutate(
    FIPS = gsub("\\D", "", as.character(FIPSTEXT)),
    FIPS = sprintf("%05d", as.numeric(FIPS))
  ) %>%
  left_join(
    county_lookup,
    by = "FIPS"
  ) %>%
  filter(
    substr(FIPS, 1, 2) == "06",
    !is.na(County)
  ) %>%
  transmute(
    County = County,

    cattle_density =
      y22_M098_valueNumeric,

    cattle_inventory =
      y22_M099_valueNumeric,

    cattle_sold =
      y22_M101_valueNumeric,

    dairy_share =
      y22_M100_valueNumeric
  ) %>%
  filter(
    !is.na(cattle_density),
    !is.na(cattle_inventory),
    !is.na(cattle_sold)
  )

# ---------------------------------------------------------
# Create hover information
# ---------------------------------------------------------

livestock_3d <- livestock_3d %>%
  mutate(
    hover_text = paste0(
      "<b>", County, "</b><br>",
      "Cattle per 100 acres: ",
      format(round(cattle_density, 1), big.mark = ","),
      "<br>",
      "Cows & heifers: ",
      format(round(cattle_inventory), big.mark = ","),
      "<br>",
      "Cattle sold: ",
      format(round(cattle_sold), big.mark = ","),
      "<br>",
      "Cows/heifers as % of cattle: ",
      format(round(dairy_share, 1)),
      "%"
    )
  )

# ---------------------------------------------------------
# Create interactive 3D visualization
# ---------------------------------------------------------

livestock_3d_plot <- plot_ly(
  data = livestock_3d,

  x = ~cattle_density,
  y = ~cattle_inventory,
  z = ~cattle_sold,

  type = "scatter3d",
  mode = "markers",

  marker = list(
    size = 7,
    color = ~dairy_share,
    colorscale = "Magma",
    opacity = 0.9,
    showscale = TRUE,

    colorbar = list(
      title = "Cows & heifers<br>% of cattle",
      titlefont = list(
        color = "#E8E5DF"
      ),
      tickfont = list(
        color = "#E8E5DF"
      )
    )
  ),

  text = ~hover_text,
  hoverinfo = "text"
) %>%

  layout(

    # -----------------------------------------------------
    # TITLE
    # -----------------------------------------------------

    title = list(
      text = "California's Livestock Landscape",
      font = list(
        color = "#F2EFE9",
        size = 24
      ),
      x = 0.03,
      xanchor = "left",
      y = 0.98,
      yanchor = "top"
    ),

    # -----------------------------------------------------
    # EXTRA SPACE ABOVE THE GRAPH
    # -----------------------------------------------------

    margin = list(
      t = 110,
      r = 40,
      b = 40,
      l = 40
    ),

    paper_bgcolor = "#0B0D0E",

    # -----------------------------------------------------
    # 3D SCENE
    # -----------------------------------------------------

    scene = list(

      bgcolor = "#0B0D0E",

      xaxis = list(
        title = "Cattle per 100 acres",
        color = "#E8E5DF",
        gridcolor = "#303438",
        zerolinecolor = "#555555",
        titlefont = list(
          color = "#E8E5DF"
        )
      ),

      yaxis = list(
        title = "Cows & heifers inventory",
        color = "#E8E5DF",
        gridcolor = "#303438",
        zerolinecolor = "#555555",
        titlefont = list(
          color = "#E8E5DF"
        )
      ),

      zaxis = list(
        title = "Cattle sold",
        color = "#E8E5DF",
        gridcolor = "#303438",
        zerolinecolor = "#555555",
        titlefont = list(
          color = "#E8E5DF"
        )
      ),

      camera = list(
        eye = list(
          x = 1.5,
          y = 1.5,
          z = 1.2
        )
      )
    )
  )

# Display the visualization
livestock_3d_plot