Author:

| Published:

| Updated:


This post describes complete code to create 72 maps from 24 Excel sheets in distributed in 4 Excel files in R. I map of US to demonstrate the visualization process. These 72 maps were saved automatically in local directory and are compiled into six pages by creating a grid of 4 by 3 matrix per page using LaTeX. To further explain the nature of data, I have four excel files. In each of the two among four excel files, I have eight sheets. Other two excel files have four sheets per file. That makes total 24 excel sheets (2*8 + 2*4 = 24) in four excel files. In each excel sheets, I have four variables namely: 1) US county FIPS code, 2) Biomass, 3) Acres, and 4) Optimal Choice. Biomass and acres are continuous variables. Choices has four groups of choices making this variable a categorical variable. Variables I am plotting in the map are Biomass, Acres, and Optimal Choices. There are total 72 (24*3 = 72) maps to develop. Creating all these maps one by one is cumbersome. Often maps need some adjustments to make them visually appealing which further complicates the entire process making it almost impossible to handle efficiently. So, I am automating the entire process in R such that the process will become quicker and automated. This will further makes modifying maps easier as I can make changes by altering a few lines of code.

In the code below, I am automatically importing all four variables from 24 excel sheets, import mainland US tiger shapefile, select area of interest, join US shapefile with data in excel sheet and plot above mentioned three variables on US map, and save maps in local directory. The data management part is fully automated. So, this code works well to import any number of excel files stored in single folder with any number of sheets in each excel file. However, variables to plot on map should be manually input. I made plotting manual because each variable has unique plotting parameters and needs individualized customization for title, subtitle, footnote, axis, legend, etc. I have written data visualization code for both continuous and categorical variables. So, copying and pasting plotting codes as needed and changing a few parameters would easily solve the problem and provide customization flexibility instead of writing complex and single automated code for continuous and categorical variables. I will describe every chunk of code making it easier to understand.

Codes below set working directory and clean environment to keep R environment clean and keep work uninterrupted by removing unnecessary items. You must replace “//Users//directory//to//folder” by the path to the working folder on your computer. Setting up a working directory can be very simple if you are using one computer all the time. I am switching between three computers which is why I have complicated code.

######### House Keeping: ############
rm(list = ls())
######## Set Wroking Directory  ###########
Sysinfo = Sys.info()
# Office
OfficePC = "//Users//directory//to//folder"
#Mac:
MacPC = "//Users//directory//to//folder"
#Personal Window:
PersonalPC = "//Users//directory//to//folder"
ifelse(Sysinfo[4] == "user-MacBook-Pro.local",
       setwd(MacPC), 
       ifelse(Sysinfo[4] == "user-DESK", 
              setwd(PersonalPC), 
              setwd(OfficePC)))
rm(list = c("MacPC", "OfficePC", "Sysinfo"))

The code below sets up a working directory if you are using the same computer all the time to run this code. Don’t forget to replace the path to folder just like above.

######### House Keeping: ############
rm(list = ls())
######## Set Working Directory for Single Computer ###########
setwd("//Users//directory//to//folder")

Always load necessary packages before working in R. All packages listed below are not necessary to perform the task I am demonstrating in this post. I tried various options while testing multiple ways to map variables and arrange maps. Having more packages loaded is less problematic compared to not loading required packages. You may try commenting each package to see how they affect mapping and delete unnecessary packages. If you have to install the package, you may want to use install.packages() and add name of package inside ().

######## Load Packages: #########
library(readxl, warn.conflicts = FALSE, quietly = TRUE)
library(openxlsx2, warn.conflicts = FALSE, quietly = TRUE)
library(tidyverse, warn.conflicts = FALSE, quietly = TRUE)
library(grid, warn.conflicts = FALSE, quietly = TRUE)
library(dplyrAssist, warn.conflicts = FALSE, quietly = TRUE)
library(png, warn.conflicts = FALSE, quietly = TRUE)
library(imager, warn.conflicts = FALSE, quietly = TRUE)
library(magick, warn.conflicts = FALSE, quietly = TRUE)
library(progress, warn.conflicts = FALSE, quietly = TRUE)
library(gridExtra, warn.conflicts = FALSE, quietly = TRUE) # Combo Plots
library(patchwork, warn.conflicts = FALSE, quietly = TRUE) # Combo Plots
library(cowplot, warn.conflicts = FALSE, quietly = TRUE) # Combo Plots
library(ggpubr, warn.conflicts = FALSE, quietly = TRUE) # Compile plot
library(scales, warn.conflicts = FALSE, quietly = TRUE) # Plot Scale
library(sp, warn.conflicts = FALSE, quietly = TRUE) # Spatial Data
library(sf, warn.conflicts = FALSE, quietly = TRUE) # Simple Feature
library(terra, warn.conflicts = FALSE, quietly = TRUE) #
library(tigris)
#readline(prompt="Press [enter] to continue")

Below, I am importing the US Shapefile. I downloaded the Tiger Shapefile manually and imported it to R from the computer directory. However, this can be done using the “tigris” package in R. Readline pauses R before jumping to the next step and force you to hit ‘enter’ for R to work further. This is good way to minimize errors while working with large data. Then I subset only the area of my interest and fix error on the shape file using st_make_valid(). If you fail to do so, shapefile may not always works properly. I further merge county boundaries to create state boundary and further merge state bondaries to create outer boundary of area of interest. I saved created files into local directory using “save.image” because this process is very time and power consuming.

##### Import Map Shapefiles and Manipulate Study Area #####
readline(prompt="Press [enter] to continue")
# Import US Map with Counties:
usstates = read_sf(".\\USCounties\\Mainland USA Counties.shp") %>%
  select(NAME, STATE_NAME, STATE_ABBR, STATE_FIPS, COUNTY_FIP, FIPS) %>%
  mutate(FIPS = as.numeric(FIPS))

# Subset study area:
study.aoi = usstates %>%
  filter(STATE_ABBR == "ND" | STATE_ABBR == "SD" | STATE_ABBR == "NE" |
           STATE_ABBR == "KS" | STATE_ABBR == "OK" | STATE_ABBR == "TX" |
           STATE_ABBR == "MN" | STATE_ABBR == "IA" | STATE_ABBR == "MO" |
           STATE_ABBR == "AR" | STATE_ABBR == "LA" | STATE_ABBR == "WI" |
           STATE_ABBR == "IL" | STATE_ABBR == "MS" | STATE_ABBR == "MI" |
           STATE_ABBR == "IN" | STATE_ABBR == "OH" | STATE_ABBR == "KY" |
           STATE_ABBR == "TN" | STATE_ABBR == "AL" | STATE_ABBR == "GA" |
           STATE_ABBR == "FL" | STATE_ABBR == "SC" | STATE_ABBR == "NC" |
           STATE_ABBR == "VA" | STATE_ABBR == "WV" | STATE_ABBR == "PA" |
           STATE_ABBR == "NY" | STATE_ABBR == "VT" | STATE_ABBR == "NH" |
           STATE_ABBR == "ME" | STATE_ABBR == "MA" | STATE_ABBR == "RI" |
           STATE_ABBR == "CT" | STATE_ABBR == "NJ" | STATE_ABBR == "DE" |
           STATE_ABBR == "MD") %>% st_make_valid()

# Create study area state boundary:
aoi.st.bound = study.aoi %>%
  group_by(STATE_FIPS) %>%
  summarize()

# Create study area global boundary:
aoi.gl.bound = st_union(aoi.st.bound,
                        is_coverage = FALSE)
save.image("./R Files/Large Boundary File.RData")

This code writes a progress bar that prints messages about the total data processed and time taken. This ensures your computer is working behind the scenes. This code is optional. If you exclude this code, you may have to take out “f()” from the code to avoid errors. If you keep this code, it will be fun to watch the process while computer is processing the map data.

####### Progress Bar #####
pb = progress_bar$new(
  format = "Processing data at :rate. Processed :bytes in :elapsed.",
  clear = TRUE,
  total = NA, 
  width = 80)
f = function() {
  for (i in 1:100) {
    pb$tick(sample(1:100 * 1000, 1))
    Sys.sleep(2/100)
  }
  pb$tick(1e7)
  #invisible()
}

There is lot going on the code below. load(“./R Files/Large Boundary File.RData”) is used to load previously saved data using “save.image”. Else, you don’t need this code. Rest code imports excel file, excel sheets, variables, save excel files in list called “allxlfiles”, unlist allxlfiles, and save list of 24 excel sheets in “excelsheets” making it ready to join with Shapefile of US counties. Comments above each code are helpful to understand the process. Most comments are self explanatory. If you are in the early phase of writing R code, this may be little complicated for you and may require some research to understand the code. I wrote “xlimportfn” to import data and manipulated/cleaned variables inside the function. This is easiest way to clean data. “allxlfiles” is two-step nested list which will be unlisted to one-step list using “unlist” function. Here, the trick is to list all four excel files in allxlfiles and sub-list all excel sheet inside respective lists created by adding excel files in allxlfiles list. For simplicity, imagine allxlfiles is the folder containing all excel files. Each excel files have their respective excel sheets and each excel sheets have their respective variables. They are imported exactly as they are arranged inside the folder. Unlisting is similar to compiling all excel sheets in one excel file just like you can do in excel. Here, excel file is named as “excelsheets”. In this demonstration, four imported excel files have total 24 sheets (see math above) and thus “excelsheets” will have 24 items listed. Each 24 items have four variables just like in the excel sheets (read above if confused)

##### Import Saved Data #####
load("./R Files/Large Boundary File.RData")

##### Import Excel Files: #####
# List of excel files:
list_files = list.files("./Data Original",
                        all.files = FALSE,
                        pattern = '*.xlsx')
# Empty list to Store all excel file in a list:
allxlfiles = list()
# Empty list to store excel Sheet Names (used later):
excelsheets = list()
for (i in 1:length(list_files))
  {
  # Path of each excel file:
  xl_path = paste0("./Data Original/", 
                   list_files[[i]])
  # Names of excel sheets:
  sheet_names = excel_sheets(path = paste0(xl_path))
  # Save excel sheets in a list:
  excelsheets[[i]] = purrr::set_names(sheet_names)
  # Import Excel Data:
  xlimportfn = function(x)
    {
    # import Excel Sheet using sheet names:
    as.data.frame(read_excel(path = paste0(xl_path), 
                             sheet = x,
                             range = cell_cols("A:D"),
                             col_names = TRUE)) %>% 
      # Manipulate variables in excel as needed:
      mutate(Acre2 = ifelse(`Optimal Choice` == 1, 0, Acreage),
             BMass2 = ifelse(`Optimal Choice` == 1, 0, Biomass),
             OptCho = recode(`Optimal Choice`,
                             "1" = "Original Use",
                             "2" = "Fixed Price",
                             "3" = "Revenue Sharing",
                             "4" = "Lease"))
    }
  # Import each excel sheet in each excel file as a dataframe:
  pulled_sheet = sapply(sheet_names, xlimportfn, simplify = FALSE)
  # rename each excel sheet in each file with their respective names:
  names(pulled_sheet) = sheet_names
  # Save excel sheets in a list:
    allxlfiles[[i]] = pulled_sheet
}
# Create a list of 24 excel sheets names:
excelsheets = unlist(excelsheets,
                     recursive = TRUE,
                     use.names = TRUE)

The second large chunk of code joins excel sheets (“excelsheets”) with Shapefile (“all.shp.file”). The codes below rename variables, manipulate variables as necessary, join “excelsheets” with “all.shp.file”, calculate summary statistics from Shapefile, print summary stats, and save merged data as new Shapefile. This new shape file will be used to plot the data.

I have computed summary statistics from both Shapefile data and Excel data to check quality. This is a place where I struggled to write right code. I had to go back and forth several times to fix code until I got my code right. So, this is the best way to check quality of work you are doing before generating plots. I also generated statistics for large and small producers. Some of the codes are not necessary to generate visualization. However they are useful in exploring data and ensuring quality of tasks. If you want to use this code to import very large number of excel files each with very large number of sheets and variables, I suggest computing summary statistics separately. Read comments before each line of code to understand code. Some additional research may be necessary for early coders to understand code.

###### Join excel file with map: #####
# Save shp file after joining:
all.shp.files = list()
# loop to join excel files to shape files:
for (i in 1: length(allxlfiles)) {
  tempshpfiles = list()
  singlexlf = allxlfiles[[i]]
  for (j in 1:length(singlexlf)) {
    tempdf = singlexlf[[j]]
    # Give names to your variables.
    names(tempdf) = c("FIPS", "`Optimal Choice`", "Acre", "BioMass", 
                      "Acre2", "BioMass2", "OptCho")
    # Join Excel and shape file:
    xlNsf = study.aoi %>%
      left_join(tempdf,
                na = TRUE,
                by = c("FIPS" = "FIPS")) %>%
      mutate(Acre = as.numeric(Acre),
             BioMass = as.numeric(BioMass),
             Acre2 = as.numeric(Acre2),
             BioMass2 = as.numeric(BioMass2))
    # Summary statistics from shapefile:
    xlnsfsummary = as.data.frame(xlNsf) %>%
      select(OptCho, Acre, BioMass, Acre2, BioMass2) %>% 
      group_by(OptCho) %>%
      summarise(MAC = mean(Acre),
                MBM = mean(BioMass),
                MAC2 = mean(Acre2),
                MBM2 = mean(BioMass2),
                FOC = n())
    # print summary statistics:
    # print(xlnsfsummary)
    # print(head(xlNsf[, 7:13]))
    tempshpfiles[[j]] = xlNsf
  }
  all.shp.files[[i]] = tempshpfiles
  rm(tempshpfiles)
}
# Make a single list of 24 shp and rename with excel sheet names:
all.shp.files = unlist(all.shp.files,
                     recursive = FALSE,
                     use.names = TRUE)
names(all.shp.files) = lapply(excelsheets,
                            function(x) paste0(x))
############### Summary Statistics: ############## # Summary Statistics From all Excel Files: # Extract Each Tabs all.summary.xl = list() for (i in 1:length(allxlfiles)) { f() temp.summary.xl = list() # List of all excel files: xlf = allxlfiles[[i]] # Excel File for (j in 1:length(xlf)) { tempdf = as.data.frame(xlf[[j]]) names(tempdf) = c("FIPS", "`Optimal Choice`", "Acre", "BioMass", "Acre2", "BioMass2", "OptCho") # Calculate Summary Statistics: cat(fill = TRUE) print(paste0("This Excel Sheet is ", names(allxlfiles[[i]][j]))) tempsummary.xl = tempdf %>% group_by(OptCho) %>% summarise( OC_Fq = n(), # Number of Counties AC_Sum = sum(Acre2), # Total Acres BM_Sum = sum(BioMass2), # Total Biomass AC_Mean = mean(Acre2), # Average Acres BM_Mean = mean(BioMass2), # Average Biomass FOC2 = table(OptCho)) temp.summary.xl[[j]] = tempsummary.xl summary.xl = tempdf %>% summarise(BM_Total = sum(BioMass2), OC_total = n(), AC_Total = sum(Acre2)) print(tempsummary.xl) print(summary.xl) } all.summary.xl[[i]] = temp.summary.xl rm(temp.summary.xl) } # Rename 24 summary with respective excel sheet name: all.summary.xl = unlist(all.summary.xl, recursive = FALSE, use.names = TRUE) names(all.summary.xl) = lapply(excelsheets, function(x) paste0(x)) # Summary Statistics From Shape File: # Extract Each Tab all.producers.summary = list() small.producers.summary = list() large.producers.summary = list() for (i in 1:length(all.shp.files)) { f() # List of all excel files: ashpf = as.data.frame(all.shp.files[[i]]) # Calculate Summary Statistics: temp.all = ashpf %>% select(OptCho, Acre, BioMass, Acre2, BioMass2) %>% group_by(OptCho) %>% summarise(OC_Fq = n(), # Number of Counties BM_Min = min(BioMass2), # Min Biomass BM_Max = max(BioMass2), # Max Biomass BM_Mean = mean(BioMass2), # Avg Biomass BM_Sum = sum(BioMass2), # Total Biomass AC_Min = min(Acre2), # Land Min AC_Max = max(Acre2), # Land Max AC_Mean = mean(Acre2), # Land Avg AC_Sum = sum(Acre2)) all.producers.summary[[i]] = temp.all # Small Producers: temp.small = ashpf %>% group_by(OptCho) %>% filter(STATE_ABBR == "FL" | STATE_ABBR == "GA" | STATE_ABBR == "MI" | STATE_ABBR == "AL" | STATE_ABBR == "NC" | STATE_ABBR == "SC") %>% summarise(OC_Fq = n(), # Number of Counties BM_Min = min(BioMass2), # Min Biomass BM_Max = max(BioMass2), # Max Biomass BM_Mean = mean(BioMass2), # Avg Biomass BM_Sum = sum(BioMass2), # Total Biomass AC_Min = min(Acre2), # Land Min AC_Max = max(Acre2), # Land Max AC_Mean = mean(Acre2), # Land Avg AC_Sum = sum(Acre2)) # Land Total small.producers.summary[[i]] = temp.small # Large Producers: temp.large = ashpf %>% group_by(OptCho) %>% filter(STATE_ABBR == "TX" | STATE_ABBR == "LA" | STATE_ABBR == "KY" | STATE_ABBR == "OK") %>% summarise(OC_Fq = n(), # Number of Counties BM_Min = min(BioMass2), # Min Biomass BM_Max = max(BioMass2), # Max Biomass BM_Mean = mean(BioMass2), # Avg Biomass BM_Sum = sum(BioMass2), # Total Biomass AC_Min = min(Acre2), # Land Min AC_Max = max(Acre2), # Land Max AC_Mean = mean(Acre2), # Land Avg AC_Sum = sum(Acre2)) large.producers.summary[[i]] = temp.large # Print Summary Results: cat(fill = TRUE) print(paste0("This is ", names(all.shp.files[i]))) print("All Producers:") print(temp.all) print("Small Producers:") print(temp.small) print("Large Producers:") print(temp.large) rm(temp.all) rm(temp.large) rm(temp.small) } names(large.producers.summary) = lapply(excelsheets, function(x) paste0(x)) # Play around to covert into data frame: lps = unlist(large.producers.summary, recursive = TRUE, use.names = TRUE) # Convert List into Data frame: This might help. Play around. a = do.call(rbind, lps)

Next part in data visualization and saving maps in local directory. I wrote common theme for all maps and passed the theme parameters into individual plots using ggplot2. I have plotted two continuous variables called “Biomass” and “Acres” and one categorical variable called “Optimal Choices”. Map parameters for each variables are different and thus, individually customized.

############ Map Visualization: ###############
maptheme = ggplot() +
  theme_void() +
  # Mapping theme:
  theme(panel.background = element_rect(fill = "#FFFFFF"), # fill white
        axis.title = element_blank(),
        axis.line = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank(),
        axis.line.x = element_blank(),
        axis.line.y = element_blank(),
        panel.grid = element_blank(),
        panel.border = element_blank(),
        #plot.background = element_blank(),
        plot.margin = margin(t = 0, 
                             r = 0, 
                             b = 0, 
                             l = 0, 
                             unit = "cm"),
        # Text formatting:
        text = element_text(family = "serif", # font
                            size = 12, # font size
                            colour = "black"# font color
        ),
        legend.position = c(0.84, 0.22),
        legend.margin = margin(5, 4, 4, 4),
        legend.key = element_rect(color = "black", 
                                  fill = NA, 
                                  linewidth = 0.05, 
                                  linetype = 1),
        plot.title = element_text(hjust = 0.5))


# Plot Optimal Choice data (Discrete Data):
# plot in loop:
OC24maps = list()
for (i in 1:length(all.shp.files)) {
  f() #progress bar.
  df_i = all.shp.files[[i]]
  OC = maptheme +
    geom_sf(data = df_i,
            aes(fill = OptCho),
            na.rm = TRUE,
            color = NA,
            show.legend = TRUE) +
    # Plotting Border as theme:
    geom_sf(data = aoi.gl.bound,
            fill = NA,
            color = "black",
            size = 0.05,
            show.legend = FALSE) +
    # # Labels:
    # labs(title = element_text(names(all.shp.files[i]),
    #                              color = "black",
    #                              size = 12,
    #                              hjust = 0.5,
    #                              face = "bold")) +
    # # Text annotation:
    # annotation_custom(grid.text(names(all.shp.files[i]),
    #                             x = 0.5,
    #                             y = 0.9,
    #                             gp = gpar(col = "black",
  #                                       fontsize = 12,
  #                                       family = "serif",
  #                                       fontface = "bold"))) +
  # Colors
  scale_fill_manual(values = c("#660000", "#008000", 
                                        "#EFEFEF", "white"),
                                        breaks =  c("Fixed Price", "Revenue Sharing",
                                                    "Original Use", NA),
                    na.value = "#FFFFFF", #white
                    name = bquote(Optimal~Choices),
                    limits = c("Fixed Price", "Revenue Sharing",
                               "Original Use", NA)
  )
  OC24maps[[i]] = OC
  # Save plots to directory
  ggsave(OC,
         path = "./Created Maps",
         dpi = 320,
         height = 5,
         width = 5,
         units = "in",
         filename = paste0("OC ", names(all.shp.files)[i], ".png"))
}

# Plot Biomass/Yield data (Continuous Data):
BM24maps = list()
for (i in 1:length(all.shp.files)) {
  f() # progress bar.
  df_i = all.shp.files[[i]]
  BM = maptheme +
    geom_sf(data = df_i,
            aes(fill = BioMass2),
            na.rm = TRUE,
            color = NA,
            show.legend = TRUE) +
    # Plotting Border as theme:
    geom_sf(data = aoi.gl.bound,
            fill = NA,
            color = "black",
            size = 0.05,
            show.legend = FALSE) +
    # # Labels:
    # labs(title = element_text(names(all.shp.files[i]),
    #                              color = "black",
    #                              size = 12,
    #                              hjust = 0.5,
    #                              face = "bold")) +
    # Text annotation:
    # annotation_custom(grid.text(names(all.shp.files[i]),
    #                             x = 0.5,
    #                             y = 0.95,
    #                             gp = gpar(col = "black",
  #                                       fontsize = 12,
  #                                       family = "serif",
  #                                       fontface = "bold"))) +
  # Colors:
  scale_fill_continuous(low = "#FFFFFF", # White
                        high = "#008000", # Dark red
                        na.value = "#FFFFFF", # White
                        name = bquote(Production~(Mt.)),
                        labels = scales::number_format(big.mark = ","))
  BM24maps[[i]] = BM
  # Save plots to directory
  ggsave(BM,
         path = "./Created Maps",
         dpi = 320,
         height = 5,
         width = 5,
         units = "in",
         file = paste0("BM ", names(all.shp.files)[i], ".png"))
}

# Plot acres data (Continuous Data):
AC24maps = list()
for (i in 1:length(all.shp.files)) {
  f() # progress bar.
  df_i = all.shp.files[[i]]
  AC = maptheme +
    geom_sf(data = df_i,
            aes(fill = Acre2),
            na.rm = TRUE,
            color = NA,
            show.legend = TRUE) +
    # Plotting Border as theme:
    geom_sf(data = aoi.gl.bound,
            fill = NA,
            color = "black",
            size = 0.05,
            show.legend = FALSE) +
    # # Labels:
    # labs(title = element_text(names(all.shp.files[i]),
    #                           color = "black",
    #                           size = 12,
    #                           hjust = 0.5,
    #                           face = "bold")) +
    # # Text annotation:
    # annotation_custom(grid.text(names(all.shp.files[i]),
    #                             x = 0.5,
    #                             y = 0.95,
    #                             gp = gpar(col = "black",
    #                                       fontsize = 12,
    #                                       family = "serif",
    #                                       fontface = "bold"))) +
    # Colors:
    scale_fill_continuous(low = "#FFFFFF", # White
                          high = "#010463", # Dark Blue
                          na.value = "white",
                          name = bquote(Land~(Ha.)),
                          labels = scales::number_format(big.mark = ","))
    
    AC24maps[[i]] = AC
  # Save plots to directory
  ggsave(AC,
         path = "./Created Maps",
         dpi = 300,
         height = 5,
         width = 6,
         units = "in",
         file = paste0("AC ", names(all.shp.files)[i], ".png"))
}

This completes programming in R. So far we created 72 maps from four excel files and 24 sheets. Next step is to create composite map. There are several ways to do so in R and outside R. However, compiling 72 maps in 6 pages (12 maps per page) as I wanted was tough in R. R failed to place maps in the way I wanted it to arrange for me multiple times. Processing 72 high quality maps is time consuming as well as placement and the arrangement quality was not as expected. So, I chose to use LaTeX to generate a table of 4*3 grid per page and fit 72 maps in six page. Explaining LaTeX code is out of the scope of this post. However, I have included codes that I used in LaTeX to compile 72 maps so this post become a complete package for someone who wants to follow my approach.

\documentclass[english, letterpaper, 12pt]{article} % Document types
\usepackage{graphicx} % Image
%\usepackage{tikz} % Plotting
\usepackage[margin = 1 in]{geometry}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{float}
\usepackage[textfont=bf]{subcaption} % bold text in sub caption
\captionsetup{labelfont=bf} % bold label
\usepackage{chngcntr}
\usepackage{ragged2e}
\usepackage{multirow}
\usepackage{multicol}
\usepackage{wrapfig}
\usepackage{lscape}
\usepackage{pdflscape}
\usepackage{fancyhdr}
\usepackage{rotating}
\usepackage{epstopdf}
%\counterwithin{figure}{section} % include section number in caption of figure
% Set path to image:
\graphicspath{ {path/to/maps/created/using/R} }
% Path in Windows format:
%\graphicspath{ {c:/user/pictures/} }
%Path in Unix-like (Linux, Mac OS) format:
%\graphicspath{ {/home/user/pictures/} }
% Multiple path:
%\graphicspath{ {./pictures1/}{./pictures2/} }

\begin{document}
\begin{landscape}
% Miscanthus Optimal Choices:
\pagenumbering{gobble}
\begin{figure}[h]\centering
\begin{Center}
\vspace*{-\baselineskip}
\begin{tabular}{ccccc}
&
\multicolumn{2}{c}{\textbf{\centering{0.0001 Risk Aversion Factor}}} &
\multicolumn{2}{c}{\textbf{\centering{0.00005 Risk Aversion Factor}}} \\
&
\textbf{2\% Discount Rate} &
\textbf{10\% Discount Rate} &
\textbf{2\% Discount Rate} &
\textbf{10\% Discount Rate} \\
% \hline\small
& A & B & C & D \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{0\% Insurance Subsidy}}}} &
% \vline
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S2 M0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S4 M0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S6 M0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S8 M0.png} \\
& E & F & G & H \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{50\% Insurance Subsidy}}}} &
% \vline
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S1 M55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S3 M55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S5 M55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S7 M55.png} \\
& I & J & K & L \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{100\% Insurance Subsidy}}}} &
% \vline
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S1 M100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S3 M100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S5 M100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S7 M100.png} \\
\end{tabular}
\end{Center}
\vspace*{-\baselineskip}
\caption{Optimal choices of contracts for miscanthus production.}{
\vspace*{-\baselineskip}
\begin{FlushLeft}
\scriptsize\textit{Notes:} Maps A to D have 0\%, E to H have 55\%, and I to L have 100 \% insurance premium subsidies. Maps A, B, E, F, I, and J have 0.0001 and C, D, G, H, K, and L have 0.00005 risk aversion parameters. Maps A, C, E, G, I, and K have 2\% and B, D, F, H, J, and L have 10\% discount rates. Optimal menus for maps A are \$32 fixed price per ton (FP) and 23\% fixed revenue sharing (RS), B are \$38 FP and 27\% RS, C are \$31 FP and 23\% RS, D are \$37 FP and 26\% RS, E are \$31 FP and 23\% RS, F are \$38 FP and 26\% RS, G are \$30 FP and 22\% RS, H are \$36 FP and 25\% RS, I are \$31 FP and 22\% RS, J are \$37 FP and 26\% RS, K are \$30 FP and 21\% RS, and L are \$35 FP and 25\% RS. Fixed rental rates are \$0 for all maps.
\end{FlushLeft}
}
\label{fig:OCMis}
\end{figure}

% Miscanthus Biomass Production:
\begin{figure}[h]\centering\small
\begin{Center}
\vspace*{-\baselineskip}
\begin{tabular}{ccccc}
&
\multicolumn{2}{c}{\textbf{\centering{0.0001 Risk Aversion Factor}}} &
\multicolumn{2}{c}{\textbf{\centering{0.00005 Risk Aversion Factor}}} \\
& \textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} &
\textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} \\
& A & B & C & D \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{0\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S2 M0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S4 M0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S6 M0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S8 M0.png} \\
& E & F & G & H \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{50\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S1 M55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S3 M55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S5 M55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S7 M55.png} \\
& I & J & K & L \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{100\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S1 M100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S3 M100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S5 M100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S7 M100.png} \\
\end{tabular}
\end{Center}
\vspace*{-\baselineskip}
\caption{Miscanthus biomass production.}{
\vspace*{-\baselineskip}
\begin{FlushLeft}
\scriptsize\textit{Notes:} Maps A to D have 0\%, E to H have 55\%, and I to L have 100 \% insurance premium subsidies. Maps A, B, E, F, I, and J have 0.0001 and C, D, G, H, K, and L have 0.00005 risk aversion parameters. Maps A, C, E, G, I, and K have 2\% and B, D, F, H, J, and L have 10\% discount rates. Optimal menus for maps A are \$32 fixed price per ton (FP) and 23\% fixed revenue sharing (RS), B are \$38 FP and 27\% RS, C are \$31 FP and 23\% RS, D are \$37 FP and 26\% RS, E are \$31 FP and 23\% RS, F are \$38 FP and 26\% RS, G are \$30 FP and 22\% RS, H are \$36 FP and 25\% RS, I are \$31 FP and 22\% RS, J are \$37 FP and 26\% RS, K are \$30 FP and 21\% RS, and L are \$35 FP and 25\% RS. Fixed rental rates are \$0 for all maps.
\end{FlushLeft}
}

%\label{fig:BMMis}
\end{figure}

% Switchgrass Optimal Choices:
\begin{figure}[h]\centering\small
\begin{Center}
\vspace*{-\baselineskip}
\begin{tabular}{ccccc}
&
\multicolumn{2}{c}{\textbf{\centering{0.0001 Risk Aversion Factor}}} &
\multicolumn{2}{c}{\textbf{\centering{0.00005 Risk Aversion Factor}}} \\
& \textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} &
\textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} \\
& A & B & C & D \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{0\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S2 S0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S4 S0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S6 S0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S8 S0.png} \\
& E & F & G & H \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{50\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S1 S55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S3 S55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S5 S55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S7 S55.png} \\
& I & J & K & L \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{100\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S1 S100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S3 S100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S5 S100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {OC S7 S100.png} \\
\end{tabular}
\end{Center}
\vspace*{-\baselineskip}
\caption{Optimal choices of contracts for switch-grass production.} {
\vspace*{-\baselineskip}
\begin{FlushLeft}
\scriptsize \textit{Notes:} Maps A to D have 0\%, E to H have 55\%, and I to L have 100 \% insurance premium subsidies. Maps A, B, E, F, I, and J have 0.0001 and C, D, G, H, K, and L have 0.00005 risk aversion parameters. Maps A, C, E, G, I, and K have 2\% and B, D, F, H, J, and L have 10\% discount rates. Optimal menus for maps A are \$41 FP and 27\% RS, B are \$42 FP and 27\% RS, C are \$41 FP and 27\% RS, D are \$42 FP and 27\% RS, E are \$40 FP and 26\% RS, F are \$40 FP and 27\% RS, G are \$40 FP and 26\% RS, H are \$40 FP and 26\% RS, I are \$36 FP and 25\% RS, J are \$37 FP and 26\% RS, K are \$36 FP and 25\% RS, and L are \$37 FP and 26\% RS. Fixed rental rates are \$0 for all maps.
\end{FlushLeft}
}
\label{fig:OCSg}
\end{figure}

% Switchgrass Biomass Production:
\begin{figure}[h]\centering\small
\begin{Center}
\vspace*{-\baselineskip}
\begin{tabular}{ccccc}
&
\multicolumn{2}{c}{\textbf{\centering{0.0001 Risk Aversion Factor}}} &
\multicolumn{2}{c}{\textbf{\centering{0.00005 Risk Aversion Factor}}} \\
& \textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} &
\textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} \\
& A & B & C & D \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{0\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S2 S0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S4 S0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S6 S0.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S8 S0.png} \\
& E & F & G & H \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{50\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S1 S55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S3 S55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S5 S55.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S7 S55.png} \\
& I & J & K & L \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{100\% Insurance Subsidy}}}} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S1 S100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S3 S100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S5 S100.png} &
\includegraphics [scale=0.460, trim={2cm, 1.5cm, 0.5cm, 1.5cm}, clip] {BM S7 S100.png} \\
\end{tabular}
\end{Center}
\vspace*{-\baselineskip}
\caption{Switch-grass biomass production.}{
\vspace*{-\baselineskip}
\begin{FlushLeft}
\scriptsize \textit{Notes:} Maps A to D have 0\%, E to H have 55\%, and I to L have 100 \% insurance premium subsidies. Maps A, B, E, F, I, and J have 0.0001 and C, D, G, H, K, and L have 0.00005 risk aversion parameters. Maps A, C, E, G, I, and K have 2\% and B, D, F, H, J, and L have 10\% discount rates. Optimal menus for maps A are \$41 FP and 27\% RS, B are \$42 FP and 27\% RS, C are \$41 FP and 27\% RS, D are \$42 FP and 27\% RS, E are \$40 FP and 26\% RS, F are \$40 FP and 27\% RS, G are \$40 FP and 26\% RS, H are \$40 FP and 26\% RS, I are \$36 FP and 25\% RS, J are \$37 FP and 26\% RS, K are \$36 FP and 25\% RS, and L are \$37 FP and 26\% RS. Fixed rental rates are \$0 for all maps.
\end{FlushLeft}
}
\label{fig:BMSg}
\end{figure}

%\appendix
% Miscanthus Land (Acres):
\begin{figure}[h]\centering\small
\begin{Center}
\vspace*{-\baselineskip}
\begin{tabular}{ccccc}
&
\multicolumn{2}{c}{\textbf{\centering{0.0001 Risk Aversion Factor}}} &
\multicolumn{2}{c}{\textbf{\centering{0.00005 Risk Aversion Factor}}} \\
& \textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} &
\textbf{2\% Discount Rate} & \textbf{10\% Discount Rate} \\
& A & B & C & D \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{0\% Insurance Subsidy}}}} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S2 M0.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S4 M0.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S6 M0.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S8 M0.png} \\
& E & F & G & H \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{50\% Insurance Subsidy}}}} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S1 M55.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S3 M55.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S5 M55.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S7 M55.png} \\
& I & J & K & L \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{100\% Insurance Subsidy}}}} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S1 M100.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S3 M100.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S5 M100.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S7 M100.png}
\end{tabular}
\end{Center}
\vspace*{-\baselineskip}
\caption{Land available for miscanthus production.}{
\vspace*{-\baselineskip}
\begin{FlushLeft}
\scriptsize \textit{Notes:} Maps A to D have 0\%, E to H have 55\%, and I to L have 100 \% insurance premium subsidies. Maps A, B, E, F, I, and J have 0.0001 and C, D, G, H, K, and L have 0.00005 risk aversion parameters. Maps A, C, E, G, I, and K have 2\% and B, D, F, H, J, and L have 10\% discount rates. Optimal menus for maps A are \$32 fixed price per ton (FP) and 23\% fixed revenue sharing (RS), B are \$38 FP and 27\% RS, C are \$31 FP and 23\% RS, D are \$37 FP and 26\% RS, E are \$31 FP and 23\% RS, F are \$38 FP and 26\% RS, G are \$30 FP and 22\% RS, H are \$36 FP and 25\% RS, I are \$31 FP and 22\% RS, J are \$37 FP and 26\% RS, K are \$30 FP and 21\% RS, and L are \$35 FP and 25\% RS. Fixed rental rates are \$0 for all maps.
\end{FlushLeft}
}
\label{fig:ACMis}
\end{figure}

% Switchgrass Land (Acres):
\begin{figure}[h]\centering\small
\begin{Center}
\vspace*{-\baselineskip}
\begin{tabular}{ccccc}
&
\multicolumn{2}{c}{\textbf{\centering{0.0001 Risk Aversion Factor}}} &
\multicolumn{2}{c}{\textbf{\centering{0.00005 Risk Aversion Factor}}} \\
&
\textbf{2\% Discount Rate} &
\textbf{10\% Discount Rate} &
\textbf{2\% Discount Rate} &
\textbf{10\% Discount Rate} \\
& A & B & C & D \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{0\% Insurance Subsidy}}}} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S2 S0.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S4 S0.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S6 S0.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S8 S0.png} \\

& E & F & G & H \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{50\% Insurance Subsidy}}}} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S1 S55.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S3 S55.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S5 S55.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S7 S55.png} \\

& I & J & K & L \\
\multirow{-12}{*}{\rotatebox{90}{\centering\textbf{{100\% Insurance Subsidy}}}} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S1 S100.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S3 S100.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S5 S100.png} &
\includegraphics [scale=0.40, trim={2.5cm, 1cm, 0.5cm, 1cm}, clip] {AC S7 S100.png}
\end{tabular}
\end{Center}
\vspace*{-\baselineskip}
\caption{Land available for switch-grass production.}{
\vspace*{-\baselineskip}
\begin{FlushLeft}
\scriptsize \textit{Notes:} Maps A to D have 0\%, E to H have 55\%, and I to L have 100 \% insurance premium subsidies. Maps A, B, E, F, I, and J have 0.0001 and C, D, G, H, K, and L have 0.00005 risk aversion parameters. Maps A, C, E, G, I, and K have 2\% and B, D, F, H, J, and L have 10\% discount rates. Optimal menus for maps A are \$41 FP and 27\% RS, B are \$42 FP and 27\% RS, C are \$41 FP and 27\% RS, D are \$42 FP and 27\% RS, E are \$40 FP and 26\% RS, F are \$40 FP and 27\% RS, G are \$40 FP and 26\% RS, H are \$40 FP and 26\% RS, I are \$36 FP and 25\% RS, J are \$37 FP and 26\% RS, K are \$36 FP and 25\% RS, and L are \$37 FP and 26\% RS. Fixed rental rates are \$0 for all maps.
\end{FlushLeft}
}
\label{fig:ACSg}
\end{figure}
\end{landscape}
\end{document}

If you like to watch video demonstrating steps described above and want to know more about file structure, input, and outputs, this video may be very helpful. Enjoy the code and let me know if you have any question. Happy R Programming!

This vide describes all the process that I wrote above. You can see the structure of excel files, folders, imported data, and manipulated data in R, summary statistics generated from excel file and shape file in this video giving you a visual version of above text.

Discover more from Dr. Bijesh Mishra

Subscribe to get the latest posts sent to your email.



2 responses to “Create 72 Maps Fully Automated using R and LaTeX”

  1. Sumanta Chatterjee Avatar
    Sumanta Chatterjee

    Nice work! Could you share the excel sheets and all the data (zip folder) to reproduce the exact maps? Thanks.

    Liked by 1 person

    1. Bijesh Mishra, Ph.D. Avatar

      Thank you. Data is confidential. However this code can be used with any similar data. For data and folder structure, please watch YouTube video on the post.

      Like

Discover more from Bijesh Mishra, Ph.D.

Subscribe now to keep reading and get access to the full archive.

Continue Reading