From e68898674dbe93165016324dca27ef970121715f Mon Sep 17 00:00:00 2001
From: "Thomas J. Brailey"
Date: Sat, 1 Aug 2020 17:48:20 -0700
Subject: [PATCH] content
---
content/about.md | 2 +-
content/posts/niche_plots_I.Rmd | 8 +-
content/posts/niche_plots_I.html | 14 +-
content/posts/niche_plots_II.Rmd | 52 ++++
content/posts/niche_plots_II.html | 36 +++
content/posts/replicability.Rmd | 102 +++++++
content/posts/replicability.html | 69 +++++
content/posts/research_associate.Rmd | 50 ++++
content/posts/research_associate.html | 56 ++++
content/resume.cls | 131 +++++++++
content/tb.aux | 1 +
content/tb.log | 266 ++++++++++++++++++
...railey_resume_2020_academic.pdf => tb.pdf} | Bin 83760 -> 88399 bytes
content/tb.synctex.gz | Bin 0 -> 10248 bytes
content/tb.tex | 155 ++++++++++
content/texput.log | 19 ++
16 files changed, 951 insertions(+), 10 deletions(-)
create mode 100644 content/posts/niche_plots_II.Rmd
create mode 100644 content/posts/niche_plots_II.html
create mode 100644 content/posts/replicability.Rmd
create mode 100644 content/posts/replicability.html
create mode 100644 content/posts/research_associate.Rmd
create mode 100644 content/posts/research_associate.html
create mode 100644 content/resume.cls
create mode 100644 content/tb.aux
create mode 100644 content/tb.log
rename content/{tjbrailey_resume_2020_academic.pdf => tb.pdf} (54%)
create mode 100644 content/tb.synctex.gz
create mode 100644 content/tb.tex
create mode 100644 content/texput.log
diff --git a/content/about.md b/content/about.md
index f122c73..4880e40 100644
--- a/content/about.md
+++ b/content/about.md
@@ -11,4 +11,4 @@ I have served as a research assistant for the Center for the Study of African Po
I am interested in political institutions, elections, secession, and conflict in developing democracies, with a particular focus in sub-Saharan Africa.
-My CV can be found [here](/tjbrailey_resume_2020_academic.pdf).
\ No newline at end of file
+My CV can be found [here](/tb.pdf).
\ No newline at end of file
diff --git a/content/posts/niche_plots_I.Rmd b/content/posts/niche_plots_I.Rmd
index 59dbf12..8bff025 100644
--- a/content/posts/niche_plots_I.Rmd
+++ b/content/posts/niche_plots_I.Rmd
@@ -1,5 +1,5 @@
---
-title: "Ridiculously Niche Plots Episode I: Scaled Faceted Radar Plots with Colorful Text"
+title: "Ridiculously Niche Plots Episode I: Scaled and Faceted Radar Plots"
author: "Tom Brailey"
date: "2020-06-17"
categories: ["R"]
@@ -10,7 +10,7 @@ Hello and welcome to the first episode in a series I like to call "Ridiculously
In today's episode, we will be looking at radar plots, specifically, radar plots faceted by country, more specifically, scaled faceted radar plots with axis labels that corresponds to its legend, which groups percentages of military equipment by the domain in which they operate, and where if that percentage is 0, the axis text is grayed-out.
-To many of you I'm sure this sounds elementary, but, honestly, when I figured this out I felt a sense of achievement like no other. So, in the interesting of reliving that euphoric moment, here we go!
+To many of you I'm sure this sounds elementary, but, honestly, when I figured this out I felt a sense of achievement like no other. So, in the interest of reliving that euphoric moment, here we go!
Firstly, I do some top-secret data cleaning.
@@ -208,10 +208,10 @@ p <-
grid.arrange(arrangeGrob(
grobs = my_list,
nrow = round(length(my_sub)/2, 0),
- left = textGrob("X axis",
+ left = textGrob("Y axis",
gp = gpar(fontsize = 20),
rot = 90),
- bottom = textGrob("Y axis",
+ bottom = textGrob("X axis",
gp = gpar(fontsize = 20),
vjust = -3),
top = textGrob("Big plot",
diff --git a/content/posts/niche_plots_I.html b/content/posts/niche_plots_I.html
index f56dc24..5563b9d 100644
--- a/content/posts/niche_plots_I.html
+++ b/content/posts/niche_plots_I.html
@@ -1,5 +1,5 @@
---
-title: "Ridiculously Niche Plots Episode I: Scaled Faceted Radar Plots with Colorful Text"
+title: "Ridiculously Niche Plots Episode I: Scaled and Faceted Radar Plots"
author: "Tom Brailey"
date: "2020-06-17"
categories: ["R"]
@@ -19,7 +19,7 @@
Hello and welcome to the first episode in a series I like to call “Ridiculously Niche Plots”! An intermittent series where I give a brief rundown of especially strange plots that I have spent hours trying to crack, in the hope that someone, somewhere, struggling to understand the ins and outs of gridExtra or who are hitting their head against a wall because ggplot2 is throwing out a horrifically labyrinthine error, might stumble on this article and have all of their questions answered. I have certainly spent many hours hoping for the same…
In today’s episode, we will be looking at radar plots, specifically, radar plots faceted by country, more specifically, scaled faceted radar plots with axis labels that corresponds to its legend, which groups percentages of military equipment by the domain in which they operate, and where if that percentage is 0, the axis text is grayed-out.
-To many of you I’m sure this sounds elementary, but, honestly, when I figured this out I felt a sense of achievement like no other. So, in the interesting of reliving that euphoric moment, here we go!
+To many of you I’m sure this sounds elementary, but, honestly, when I figured this out I felt a sense of achievement like no other. So, in the interest of reliving that euphoric moment, here we go!
Firstly, I do some top-secret data cleaning.
…
beep boop
@@ -27,7 +27,7 @@
Okay, so here’s what our data looks like:
DT::datatable(tbl[1:20,])
-
+
Now we do a little bit of work to create functions and whatnot:
# This function gets all the legend information from a given ggplot object
get_legend <-
@@ -118,10 +118,14 @@
}
## Warning: Factor `country` contains implicit NA, consider using
## `forcats::fct_explicit_na`
+## Warning: Factor `domain` contains implicit NA, consider using
+## `forcats::fct_explicit_na`
## Warning: Vectorized input to `element_text()` is not officially supported.
## Results may be unexpected or may change in future versions of ggplot2.
## Warning: Factor `country` contains implicit NA, consider using
## `forcats::fct_explicit_na`
+## Warning: Factor `domain` contains implicit NA, consider using
+## `forcats::fct_explicit_na`
## Warning: Vectorized input to `element_text()` is not officially supported.
## Results may be unexpected or may change in future versions of ggplot2.
So now we have a list of ggplot objects that have all been scaled as if using the facet_grid(scales = “fixed”) argument. All we have left to do is neatly plot them together along with a single lengend rather than a legend for each plot.
@@ -138,10 +142,10 @@
grid.arrange(arrangeGrob(
grobs = my_list,
nrow = round(length(my_sub)/2, 0),
- left = textGrob("X axis",
+ left = textGrob("Y axis",
gp = gpar(fontsize = 20),
rot = 90),
- bottom = textGrob("Y axis",
+ bottom = textGrob("X axis",
gp = gpar(fontsize = 20),
vjust = -3),
top = textGrob("Big plot",
diff --git a/content/posts/niche_plots_II.Rmd b/content/posts/niche_plots_II.Rmd
new file mode 100644
index 0000000..7888edb
--- /dev/null
+++ b/content/posts/niche_plots_II.Rmd
@@ -0,0 +1,52 @@
+---
+title: "Ridiculously Niche Plots Episode II: Vessel Range from Coastline in ArcGIS"
+author: "Tom Brailey"
+date: "2020-08-01"
+categories: ["ArcGIS"]
+tags: ["ArcGIS", "path distance"]
+---
+
+
+Hello and welcome to the second episode of Ridiculously Niche Plots! Today, we are moving away from R into the realm of ArcGIS. Arc is quite a bit different to R, and reproducing outputs can be a little complicated. While there is no code to show per se, I will run through the model which is laid out in a sort of flowchart format.
+
+#### Context
+
+This project was part of my work at cPASS, specifically, Andres Gannon's dissertation on military specialization. The genesis of plot occurred as follows. Say a country that has recently joined a military alliance and acquires a new military vessel, what can the range of that vessel tell us? For example, after joining NATO, Albania acquired a military vessel that had a range of 1850 nautical miles (roughly 3426 kilometers), a range that is clearly larger than the maritime boundaries that the ship would need to patrol. Of course, it makes sense for a ship to have a larger range than is needed, but we wanted to understand just how big that range was compared to the country's maritime boundaries, and whether a ship's range gave insight into the military alliance itself.
+
+To do this, I needed to map which countries a ship with a range of 1850 nautical miles could reach. While this sounded simple to me in principal, I found this to be a far more challenging task. While it is easy to create a circle around Albania that is radius 1850 nautical miles, this is misleading as it assumes a ship can just travel in a straight line, and across land. So the question becomes, what does 1850 nautical miles look like when accounting for the presence of land?
+
+Below, you will see the flowchart layout of the model used to create a map of Albania, it's maritime boundaries, and the vessel's range. For those familiar with ArcGIS, I apologize in advance for my poor object-naming scheme; this project had gone through many iterations and by the end I had given up on naming conventions. I have named each step in the model for ease of understanding.
+
+![](/posts/niche_plots_II_files/Export Graphic.jpg)
+
+1. This plot can be replicated using three shapefiles from the web. Firstly, eez_boundaries_v11.shp is a shapefile containing information on maritime boundaries for all countries. gadm36_0.shp is a shapefile of all countries. I use this to create gadm36_0_Select2_Project_Clip.shp, which I will explain later. These files are the foundations for our visualization.
+
+2. We start by selecting just the maritime boundary for Albania.
+
+3. We then project the shapefile into a projected coordinate system that preserves distance (given that out ultimate objective is to calculate the total traversable distance of Albania's military vessels). For that, we use a European equidistant conic projection.
+
+4. Now, we create a buffer around the central point of Albania's maritime boundary. In essence, we are drawing a circle with a radius of 1850 nautical miles around the maritime boundary.
+
+5. (+ also 10) Here is where it gets a bit complicated. gadm36_0_Select2_Project_Clip.shp is created by clipping the buffer made in step 4 with the shapefile of all countries, resulting in a shapefile that is all the land that exists within the buffer. ArcGIS can be a little temperamental, and I had to write a separate model to create this output to stop the main model from breaking inexplicably (steps 8, 9, and 10 create the output, but under a different name). Anyway, we take the buffer from step four, and essentially "erase" anything that is common between that and the land within the buffer. This means that we are left with only water regions within the buffer around Albania's maritime boundary.
+
+6. We now convert the shapefile that contains all the water within the vessel's range into a raster file. When converting to raster, we are able to specify the size of each square that makes up the image -- for our purposes, we covert to kilometers.
+
+7. On opening the attributes table of the raster file, we see that each cell that makes up the image has a different value. In order to run our model later on, we need each cell to equal 1. Running "reclassify" in our case turns all values that are not equal to 1 to equal 1. The raster file is now ready to be put into the path distance model
+
+8. We now take the shapefile of all countries and remove Antarctica. This has just become a weird habit of mine...
+
+9. It is essential that all of our input files are in the same projection, otherwise our results will be completely off. Here I convert the shapefile to the European equidistant conic projection mentioned in step 3.
+
+10. Here, I subset the shapefile of all countries to just those that fall within the buffer created in step 4. Because of ArcGIS's quirks, I had to rename this file and manually read it in for it to be used for step 5.
+
+11. Now I subset the global shapefile to just include Albania. This is for both visual purposes (I want to be able to highlight where Albania is in reference to the rest of Europe) and also in order to run the main model.
+
+12. It is time to run the path distance model. The model requires two inputs, the starting point (the Albania shapefile, from step 11) and the cost raster (the output from step 7). The path distance model calculates distances from Albania while also accounting for the presence of obstacles, however, in doing so, it calculates distances that are beyond 1850 nautical miles (e.g. travelling from Albania to Norway via Portugal is within the buffer, but is more than 1850 nautical miles). As such, the final step is to filter values that are beyond the actual range of the ship. Doing so leaves us with the traversable distance of the ship, as denoted by the blue shaded area in the image below.
+
+In Arc, there are a lot of manual, and thus not really reproducible, edits you must make in order for the map to be considered publication-worthy. For example, I spent time coloring in the different shapefiles for maximum effect and clarity, adding a title, legend, and map information, and rescaling the plot to make it as clear as possible. The final product is below:
+
+![](/posts/niche_plots_II_files/albania_vessel_range.png)
+
+Quite niche indeed! This project was deceptively complicated, and more time was spent conceptualizing the problem than actually running the model. Nonetheless, it was a super interesting and enjoyable process, and I think the final product is pretty cool!
+
+That concludes the second episode of Niche Plots. Who knows what kind of weird things I will be plotting in the future...
\ No newline at end of file
diff --git a/content/posts/niche_plots_II.html b/content/posts/niche_plots_II.html
new file mode 100644
index 0000000..c62bcf8
--- /dev/null
+++ b/content/posts/niche_plots_II.html
@@ -0,0 +1,36 @@
+---
+title: "Ridiculously Niche Plots Episode II: Vessel Range from Coastline in ArcGIS"
+author: "Tom Brailey"
+date: "2020-08-01"
+categories: ["ArcGIS"]
+tags: ["ArcGIS", "path distance"]
+---
+
+
+
+Hello and welcome to the second episode of Ridiculously Niche Plots! Today, we are moving away from R into the realm of ArcGIS. Arc is quite a bit different to R, and reproducing outputs can be a little complicated. While there is no code to show per se, I will run through the model which is laid out in a sort of flowchart format.
+
+
Context
+
This project was part of my work at cPASS, specifically, Andres Gannon’s dissertation on military specialization. The genesis of plot occurred as follows. Say a country that has recently joined a military alliance and acquires a new military vessel, what can the range of that vessel tell us? For example, after joining NATO, Albania acquired a military vessel that had a range of 1850 nautical miles (roughly 3426 kilometers), a range that is clearly larger than the maritime boundaries that the ship would need to patrol. Of course, it makes sense for a ship to have a larger range than is needed, but we wanted to understand just how big that range was compared to the country’s maritime boundaries, and whether a ship’s range gave insight into the military alliance itself.
+
To do this, I needed to map which countries a ship with a range of 1850 nautical miles could reach. While this sounded simple to me in principal, I found this to be a far more challenging task. While it is easy to create a circle around Albania that is radius 1850 nautical miles, this is misleading as it assumes a ship can just travel in a straight line, and across land. So the question becomes, what does 1850 nautical miles look like when accounting for the presence of land?
+
Below, you will see the flowchart layout of the model used to create a map of Albania, it’s maritime boundaries, and the vessel’s range. For those familiar with ArcGIS, I apologize in advance for my poor object-naming scheme; this project had gone through many iterations and by the end I had given up on naming conventions. I have named each step in the model for ease of understanding.
+
+
+This plot can be replicated using three shapefiles from the web. Firstly, eez_boundaries_v11.shp is a shapefile containing information on maritime boundaries for all countries. gadm36_0.shp is a shapefile of all countries. I use this to create gadm36_0_Select2_Project_Clip.shp, which I will explain later. These files are the foundations for our visualization.
+We start by selecting just the maritime boundary for Albania.
+We then project the shapefile into a projected coordinate system that preserves distance (given that out ultimate objective is to calculate the total traversable distance of Albania’s military vessels). For that, we use a European equidistant conic projection.
+Now, we create a buffer around the central point of Albania’s maritime boundary. In essence, we are drawing a circle with a radius of 1850 nautical miles around the maritime boundary.
+(+ also 10) Here is where it gets a bit complicated. gadm36_0_Select2_Project_Clip.shp is created by clipping the buffer made in step 4 with the shapefile of all countries, resulting in a shapefile that is all the land that exists within the buffer. ArcGIS can be a little temperamental, and I had to write a separate model to create this output to stop the main model from breaking inexplicably (steps 8, 9, and 10 create the output, but under a different name). Anyway, we take the buffer from step four, and essentially “erase” anything that is common between that and the land within the buffer. This means that we are left with only water regions within the buffer around Albania’s maritime boundary.
+We now convert the shapefile that contains all the water within the vessel’s range into a raster file. When converting to raster, we are able to specify the size of each square that makes up the image – for our purposes, we covert to kilometers.
+On opening the attributes table of the raster file, we see that each cell that makes up the image has a different value. In order to run our model later on, we need each cell to equal 1. Running “reclassify” in our case turns all values that are not equal to 1 to equal 1. The raster file is now ready to be put into the path distance model
+We now take the shapefile of all countries and remove Antarctica. This has just become a weird habit of mine…
+It is essential that all of our input files are in the same projection, otherwise our results will be completely off. Here I convert the shapefile to the European equidistant conic projection mentioned in step 3.
+Here, I subset the shapefile of all countries to just those that fall within the buffer created in step 4. Because of ArcGIS’s quirks, I had to rename this file and manually read it in for it to be used for step 5.
+Now I subset the global shapefile to just include Albania. This is for both visual purposes (I want to be able to highlight where Albania is in reference to the rest of Europe) and also in order to run the main model.
+It is time to run the path distance model. The model requires two inputs, the starting point (the Albania shapefile, from step 11) and the cost raster (the output from step 7). The path distance model calculates distances from Albania while also accounting for the presence of obstacles, however, in doing so, it calculates distances that are beyond 1850 nautical miles (e.g. travelling from Albania to Norway via Portugal is within the buffer, but is more than 1850 nautical miles). As such, the final step is to filter values that are beyond the actual range of the ship. Doing so leaves us with the traversable distance of the ship, as denoted by the blue shaded area in the image below.
+
+
In Arc, there are a lot of manual, and thus not really reproducible, edits you must make in order for the map to be considered publication-worthy. For example, I spent time coloring in the different shapefiles for maximum effect and clarity, adding a title, legend, and map information, and rescaling the plot to make it as clear as possible. The final product is below:
+
+
Quite niche indeed! This project was deceptively complicated, and more time was spent conceptualizing the problem than actually running the model. Nonetheless, it was a super interesting and enjoyable process, and I think the final product is pretty cool!
+
That concludes the second episode of Niche Plots. Who knows what kind of weird things I will be plotting in the future…
+
diff --git a/content/posts/replicability.Rmd b/content/posts/replicability.Rmd
new file mode 100644
index 0000000..ce62416
--- /dev/null
+++ b/content/posts/replicability.Rmd
@@ -0,0 +1,102 @@
+---
+title: "A Brief Note on Replication in R"
+author: "Tom Brailey"
+date: "2020-07-15"
+categories: ["R"]
+tags: ["R", "replication"]
+---
+
+Replication studies -- repeating an existing study/experiment/analysis to see if the results hold up -- in the social sciences are essential for the advancement of scientific understanding. [See this Vox article for a primer](https://www.vox.com/science-and-health/2018/8/27/17761466/psychology-replication-crisis-nature-social-science#:~:text=One%20of%20the%20cornerstone%20principles,we%20can't%20be%20sure.).
+
+On a smaller scale, labs often get their researchers to run what are known as "code audits". If one researcher is working on an analysis, they hand it over to another researcher for them to run and see if the results are replicable. This process usually involves the sharing of Dropbox folders and Github repositories and code scripts. Perhaps I am being intensely persnickety about this, but I believe that if you are given an R script and have to change *anything* in order for it to run, then it is not replicable. Code audits should be quick and easy to run, giving the researchers more time to spend on actual debugging and streamlining.
+
+Here is an overview of a common set up for research projects:
+
+- Main Dropbox (MOUs, PAPs, manuscripts, admin, raw data, interim data, final cleaned data, etc.)
+
+- Github repository (set up using version control. Found in a separate folder in Dropbox)
+
+ - This is where all the cleaning and analysis code lives. Scripts should call from the main Dropbox's raw data folder, run the cleaning and analysis, then save the final data in the cleaned data folder of the main Dropbox
+
+
+Additionally, I have established a few personal rules when creating a script that I know I will being handing off to someone else for an audit.
+
+#### File paths
+I have seen lots of different ways to set file paths and directories, and most of the time, given that we all have different folder naming conventions, auditing codes requires editing these file paths. It's not a huge deal but this is how we make mistakes and accidentally save datasets in weird places and never find them again (...definitely not speaking from experience...). When specifying your "root", i.e. the main location where raw data and other core project files exist, I do the following:
+
+```{r, eval = F}
+root <- paste0("/Users/", Sys.getenv("USERNAME"), "/Dropbox/")
+```
+
+Now this will set the root to be the computer's user's Dropbox folder, which, if everyone is using Dropbox, will replicate across users. From this root, you can set other specific file paths as necessary.
+
+Another thing to note, many projects are split between a main Dropbox folder and a Github repository that essentially talk to one another. When specifying paths for the Github repository, I use a specific package.
+
+```{r, eval = F}
+github <- paste0(here::here())
+```
+
+This sets the working directory to be the location of the project you are working on, for example:
+
+"C:/Users/my_username/Dropbox/github/my_repo"
+
+Again this is just personal preference, I tend to have a script that is solely for specifying individual file paths. For example, I set file paths for input data, output data, summary statistics and graphs, tables for the manuscript, and so on. Doing this with the "here" package is super simple.
+
+```{r, eval = F}
+tbls_fr_manuscript <- paste0(here::here(), "/exhibits/for_manuscript")
+```
+
+Then, when you've made your lovely .tex table, you can save it with ease. And as long as you are sharing the entire project structure with the auditor, everything will replicate and run smoothly.
+
+```{r, eval = F}
+print(xtable(tbl_A, type = "latex"), file = paste0(tbls_fr_manuscript, "/tbl_A.tex"))
+```
+
+#### Calling packages
+
+Another thing I've noticed that can cause problems for auditors is the installing and loading of packages at the start of the script. This presents a few issues. First, if you are installing and loading packages each time you re-run the code, it is time consuming and often requires you to reboot R. Second, and most importantly, it creates issues with dependency. If you load all necessary packages at once, and, say, two packages have a similarly-named command, then this can produce errors when running the code. This is because R might confuse one command as being from one package when it is actually from another. For example, base R and dplyr both have the command "select" and if you load dplyr at the start of the script and later call select, R might not recognize that it is from that package. This is becoming an increasingly common issue given the proliferation of packages in R. My solution, though a little verbose, does the trick. It is also useful for debugging. It is better to dive straight into the problem rather than spending time trying to figure out where the command comes from and what it does.
+
+Instead of installing and loading packages at the start of the script, you call them up in line. If an auditor needs to install a package on their machine, R will tell them what packages are used in the script and whether it needs to be installed or not. Note that the only packages I specifically call at the start of a script are magrittr (for the pipe function) and ggplot2 (just because it's convenient).
+
+```{r, eval = F}
+my_data %>%
+ dplyr::mutate(new_var = old_var + 100,
+ string_var = stringr::str_replace(string_var, "_000", "")) %>%
+ tidyr::pivot_longer(-keep_var, names_to = "name", values_to = "value")
+```
+
+If you *really* don't want to use library() in your scripts, you could do the following to call the pipe function:
+
+```{r, eval = F}
+`%>%` <- magrittr::`%>%`
+```
+
+So yes, there is a little more writing required, but the payoff is clear, concise, and more easily debuggable code.
+
+#### rm(list=ls())
+
+Lot's of scripts I see start with this. While it might be nice to clear the workspace before running everything, it doesn't really clear the workspace in a meaningful way, and auditors who are working on something else might accidentally lose their work if they start working on auditing your code (again, definitely not talking from experience...).
+
+#### Comments
+
+Lastly, and more generally, a good piece of reproducible code will have lots of comments. I enumerate a few key points below:
+
+- For each chunk, i.e. each for loop, ggplot, function, etc., have a header comment outlining what exactly it does.
+
+- Then, for each line of code, have an in-line comment that states what that code does. Are we taking the log of a variable? Are we replacing values that equal -99 with NA? While keeping this concise and short, it is also often useful to include a note on *why* you are doing that thing, too. An explanation of why can also come at the start of the chunk in order to avoid cluttering the code itself.
+
+- Avoid comments that superfluous/humorous/otherwise unnecessary. If, when you read back through the code, you realize that a comment doesn't add to the overall clarity of your code, then it is best to delete it.
+
+- Avoid abbreviations. It's better for the comments to be a bit longer and be very clear than shorter and hard to decipher.
+
+- At the end of a chunk of code, if applicable, have a note on what should have been produced. For example, if you have a for loop that creates a bunch of new variables, state how many new variables should have been created, their class, their naming format, and their purpose. While one could reasonably ascertain what the code is doing, and figure out what the output would do, it is better to have it in writing to avoid any unnecessary confusion and time-wasting.
+
+I tend to use these commenting conventions for all pieces of code that I write, from analysis and cleaning scripts, to user-defined functions, and so on.
+
+#### Other
+
+More specific to code auditing, it is really useful to have an audit document that basically contains all the meta information for the code that you are handing off to someone. For me, I find MS Excel/Googlesheets to be the best format for these audit documents. One sheet will contain an overview of how all the different scripts relate to each other -- you can usually figure this out just by looking at the file structure in your Dropbox, but I like to have a single document that outlines where each script is located and its dependencies. A second sheet will contain a list of outputs/exhibits that you expect the auditor to replicate. The name of the exhibit as well as the script that contains the code to produce the output should be mentioned, and there should be space for the auditor to leave comments and suggestions, or flag errors if the exhibit is not produced as expected. A third sheet contains a list of to-dos. These will be a mix of errors flagged from the outputs sheet, as well as any general suggestions and issues.
+
+This is a good framework for collaborative code audits. Of course, depending on the complexity of the code that one is sending off for audit, it might be useful to include sheets that outline particularly complex or highly interdependent processes, say, certain variables are created and how they are then used to create other variables. If you think that your in-line comments can't quite fully capture what is going on, or if the auditor isn't super familiar with the context of your project, a more thorough summary might be in order.
+
+That's everything I've got for now. I will probably add more to this article as I read more about reproducible research and code audits and whatnot. If anyone reads these blog posts and wants to add anything to this document, leave a comment in the [issues section](https://github.com/tjbrailey/Website/issues) of my website's Github.
\ No newline at end of file
diff --git a/content/posts/replicability.html b/content/posts/replicability.html
new file mode 100644
index 0000000..c7fc694
--- /dev/null
+++ b/content/posts/replicability.html
@@ -0,0 +1,69 @@
+---
+title: "A Brief Note on Replication in R"
+author: "Tom Brailey"
+date: "2020-07-15"
+categories: ["R"]
+tags: ["R", "replication"]
+---
+
+
+
+Replication studies – repeating an existing study/experiment/analysis to see if the results hold up – in the social sciences are essential for the advancement of scientific understanding. See this Vox article for a primer.
+On a smaller scale, labs often get their researchers to run what are known as “code audits”. If one researcher is working on an analysis, they hand it over to another researcher for them to run and see if the results are replicable. This process usually involves the sharing of Dropbox folders and Github repositories and code scripts. Perhaps I am being intensely persnickety about this, but I believe that if you are given an R script and have to change anything in order for it to run, then it is not replicable. Code audits should be quick and easy to run, giving the researchers more time to spend on actual debugging and streamlining.
+Here is an overview of a common set up for research projects:
+
+Main Dropbox (MOUs, PAPs, manuscripts, admin, raw data, interim data, final cleaned data, etc.)
+Github repository (set up using version control. Found in a separate folder in Dropbox)
+
+- This is where all the cleaning and analysis code lives. Scripts should call from the main Dropbox’s raw data folder, run the cleaning and analysis, then save the final data in the cleaned data folder of the main Dropbox
+
+
+Additionally, I have established a few personal rules when creating a script that I know I will being handing off to someone else for an audit.
+
+
File paths
+
I have seen lots of different ways to set file paths and directories, and most of the time, given that we all have different folder naming conventions, auditing codes requires editing these file paths. It’s not a huge deal but this is how we make mistakes and accidentally save datasets in weird places and never find them again (…definitely not speaking from experience…). When specifying your “root”, i.e. the main location where raw data and other core project files exist, I do the following:
+
root <- paste0("/Users/", Sys.getenv("USERNAME"), "/Dropbox/")
+
Now this will set the root to be the computer’s user’s Dropbox folder, which, if everyone is using Dropbox, will replicate across users. From this root, you can set other specific file paths as necessary.
+
Another thing to note, many projects are split between a main Dropbox folder and a Github repository that essentially talk to one another. When specifying paths for the Github repository, I use a specific package.
+
github <- paste0(here::here())
+
This sets the working directory to be the location of the project you are working on, for example:
+
“C:/Users/my_username/Dropbox/github/my_repo”
+
Again this is just personal preference, I tend to have a script that is solely for specifying individual file paths. For example, I set file paths for input data, output data, summary statistics and graphs, tables for the manuscript, and so on. Doing this with the “here” package is super simple.
+
tbls_fr_manuscript <- paste0(here::here(), "/exhibits/for_manuscript")
+
Then, when you’ve made your lovely .tex table, you can save it with ease. And as long as you are sharing the entire project structure with the auditor, everything will replicate and run smoothly.
+
print(xtable(tbl_A, type = "latex"), file = paste0(tbls_fr_manuscript, "/tbl_A.tex"))
+
+
+
Calling packages
+
Another thing I’ve noticed that can cause problems for auditors is the installing and loading of packages at the start of the script. This presents a few issues. First, if you are installing and loading packages each time you re-run the code, it is time consuming and often requires you to reboot R. Second, and most importantly, it creates issues with dependency. If you load all necessary packages at once, and, say, two packages have a similarly-named command, then this can produce errors when running the code. This is because R might confuse one command as being from one package when it is actually from another. For example, base R and dplyr both have the command “select” and if you load dplyr at the start of the script and later call select, R might not recognize that it is from that package. This is becoming an increasingly common issue given the proliferation of packages in R. My solution, though a little verbose, does the trick. It is also useful for debugging. It is better to dive straight into the problem rather than spending time trying to figure out where the command comes from and what it does.
+
Instead of installing and loading packages at the start of the script, you call them up in line. If an auditor needs to install a package on their machine, R will tell them what packages are used in the script and whether it needs to be installed or not. Note that the only packages I specifically call at the start of a script are magrittr (for the pipe function) and ggplot2 (just because it’s convenient).
+
my_data %>%
+ dplyr::mutate(new_var = old_var + 100,
+ string_var = stringr::str_replace(string_var, "_000", "")) %>%
+ tidyr::pivot_longer(-keep_var, names_to = "name", values_to = "value")
+
If you really don’t want to use library() in your scripts, you could do the following to call the pipe function:
+
`%>%` <- magrittr::`%>%`
+
So yes, there is a little more writing required, but the payoff is clear, concise, and more easily debuggable code.
+
+
+
rm(list=ls())
+
Lot’s of scripts I see start with this. While it might be nice to clear the workspace before running everything, it doesn’t really clear the workspace in a meaningful way, and auditors who are working on something else might accidentally lose their work if they start working on auditing your code (again, definitely not talking from experience…).
+
+
+
+
Other
+
More specific to code auditing, it is really useful to have an audit document that basically contains all the meta information for the code that you are handing off to someone. For me, I find MS Excel/Googlesheets to be the best format for these audit documents. One sheet will contain an overview of how all the different scripts relate to each other – you can usually figure this out just by looking at the file structure in your Dropbox, but I like to have a single document that outlines where each script is located and its dependencies. A second sheet will contain a list of outputs/exhibits that you expect the auditor to replicate. The name of the exhibit as well as the script that contains the code to produce the output should be mentioned, and there should be space for the auditor to leave comments and suggestions, or flag errors if the exhibit is not produced as expected. A third sheet contains a list of to-dos. These will be a mix of errors flagged from the outputs sheet, as well as any general suggestions and issues.
+
This is a good framework for collaborative code audits. Of course, depending on the complexity of the code that one is sending off for audit, it might be useful to include sheets that outline particularly complex or highly interdependent processes, say, certain variables are created and how they are then used to create other variables. If you think that your in-line comments can’t quite fully capture what is going on, or if the auditor isn’t super familiar with the context of your project, a more thorough summary might be in order.
+
That’s everything I’ve got for now. I will probably add more to this article as I read more about reproducible research and code audits and whatnot. If anyone reads these blog posts and wants to add anything to this document, leave a comment in the issues section of my website’s Github.
+
diff --git a/content/posts/research_associate.Rmd b/content/posts/research_associate.Rmd
new file mode 100644
index 0000000..bebf37e
--- /dev/null
+++ b/content/posts/research_associate.Rmd
@@ -0,0 +1,50 @@
+---
+title: "From RA to RA"
+author: "Tom Brailey"
+date: "2020-07-28"
+categories: ["Misc"]
+tags: ["Research assistant", "Research assoicate"]
+---
+
+In June 2020, I finished up my research assistant positions at UC San Diego's (UCSD) political science department, and in July, I began working as a research associate for J-PAL's Payments and Governance Research Program (PGRP), also at UCSD. Now I have been working there for about a month, I wanted to ruminate about the transition from RA to RA.
+
+Me, being my naive and excitable self, dove head first into PGRP, assuming it to be a full-time version of the work I had been doing for the political science department. A typical workday at the department would go: get tagged in an issue ticket where the task was to create a type of graph, wrangle a dataset in a particular way, or complete a given amount of data-entry. From there, I would spend usually a day or so completing that task, checking-in regularly with my supervisor (either a PhD student or a professor) to clarify questions and arrange next-steps, and then I would move on to the next task. This set up was great for me, quick tasks that usually taught me a new skill--I would be forced to figure out how to make a waffle plot or calculate a certain statistic--and that I could complete in a couple of hours, allowing me to focus on school-related work for the rest of the day. Moreover, I never felt a huge amount of responsibility as I was just working from graph to graph, dataset to dataset, with clear instruction and little room for misunderstanding.
+
+An aside, I had an absolutely fantastic experience with all the research assistant positions that I held. However, I have colleagues who have had wildly different experiences, and so while this post maintains a warm view toward research assistantships, the darker sides of such positions--not getting paid, being over- and under-worked, workplace misconduct, and the like--need to be acknowledged.
+
+I enjoyed this style of work, and somewhat foolishly thought that a full-time research associate position would be, in essence, the same. Get given a graph to make or some data to clean or a manuscript to proofread, but all day long. What fun! When you look at the job description for a research assistant and a research associate--in political science and economics at least--they look about the same, and, from my perspective at least, no one ever really distinguished between the two, and so going into my new position, I assumed that, aside from the time commitment, they were the same position.
+
+In fact, the jump from research assistant to associate was a fairly big one. A lot fo the work is actually quite similar; you spend a lot of time cleaning and analyzing data, making graphs, and so on, but the, for lack of a better word, "vibe", is entirely different. Perhaps the biggest shock to the system is the self-organization piece. No longer am I being instructed to make a specific graph or clean a specific dataset; it is now my job to define the work agenda, what tasks need doing, and in what order. Of course, there is a PI, a project manager, and usually a few other research associates that allow you to talk through ideas a and get clarity, but for the most part, you are in charge of day-to-day operations. Of course, people will come to you with requests, which I certainly enjoy, though this is not the day-to-day norm. I enumerate a couple of tactics that I have implemented since starting my position later, but for me, the lack of explicit guidance has been the biggest challenge for me, coming from a research assistant position.
+
+The lack of instruction is exacerbated by the position being full-time. As a part-time researcher, I would intersperse work with my classes and extra-cirriculars, and I wouldn't usually focus on work-related tasks for more than three hours at a time. Now, I am up at 7, and I work until 4, and I have to fill my *entire* day with stuff to do!
+
+Another aside, maybe, in actual fact, the jump from RA to RA is really no big deal, and what actually caused my existential crises was, you know, the big old pandemic that happened at exactly the same time. So I should perhaps say that everything I am saying might want to be taken with a pinch of salt.
+
+Third, and perhaps more logically, the sheer volume and scope of your responsibilities may be overwhelming at first. You will need to familiarize yourself with vast repositories of data, manuscripts, tracking sheets, instruments; long and complicated variable naming conventions; and code that you will have literally no idea of what it is supposed to do. All of these points are to be expected of any new job, but again, if you were me, going into this with a very rudimentary understanding of the concept of "full-time research", it can all seem a little overwhelming.
+
+So, having worked as a research associate for about a month, what have I learned? Firstly, pandemics suck. Secondly, I enumerate a couple of points below that might be of use if you find yourself transitioning between a research assistantship and a research associate position:
+
+1. **Ask lots of questions**
+ + Obviously, it is good to try to figure things out for yourself, but set a limit on how much time you are going to spend on trying to make sense of something before reaching out to the right person.
+ + Additionally, when asking questions or making requests of others, it is good to:
+ + Enumerate any questions to maintain clarity.
+ + Specify a deadline of when you would like them to respond.
+ + It can also be useful to have a "questions/answers" document to keep record of particular issues. It is useful if you need reminding yourself, or if you end up handing your work off to others.
+
+2. **Keep a list of things to do**
+ + Try to keep your documents streamlined, and have all of your to dos in one document.
+ + Not a popular opinion, but I tend to shy away from using colors/fonts/sizes etc., instead crossing out goals as I complete them.
+ + Prioritize in terms of importance, not in terms of how easy something is to achieve.
+
+3. **Set daily, weekly, and monthly goals**
+ + Again, prioritize the important things. Try not to spend your time working on the small things in order to feel a sense of achievement (I say this, but I also do this literally all of the time).
+ + Be honest with yourself and with the task in hand. Based on how other tasks similar to this one have gone, how long do you *really* think you will need in order to finish it.
+ + Hold others accountable, and have others hold you accountable in completing these goals.
+ + Sometimes, a task is unexpectedly difficult. If you think it will take longer than planned, and if you promised someone you would get something to them by a deadline, be upfront, clear, and reoganize.
+
+4. **Document things**
+ + If there is a particular facet of the project that is confusing to you, writing it out can be useful.
+ + For example, if there is an analysis file that calls in a bunch of other scripts, it could be useful to use an Excel sheet to visualize how all the code files relate to one another. Going further, you could document the inputs into each script, as well as the expected outputs.
+ + Where I have a general understanding of something, and I know that the only way I am going to become super comfortable with it is exposure to it, I find documenting, writing about, or visualizing the thing to be very helpful.
+ + I find using apps like Googlesheets and Googledocs to be the most efficient and the easiest to integrate into my workflow. But as you accrue more and more documents, be them for note-taking, goal-setting, question-answering, and so on, make sure you have a clear and understandable file strucutre.
+ + I have a folder that is comprised of all documents relating to my work. It is clearly and concisely categorized and fairly easy to navigate. My thought process when creating it was to make something that I could one day hand off to the next research associate for them to use. With that in mind, I think having a folder on all things project related can be very useful for you and for the others you work with.
\ No newline at end of file
diff --git a/content/posts/research_associate.html b/content/posts/research_associate.html
new file mode 100644
index 0000000..288053f
--- /dev/null
+++ b/content/posts/research_associate.html
@@ -0,0 +1,56 @@
+---
+title: "From RA to RA"
+author: "Tom Brailey"
+date: "2020-07-28"
+categories: ["Misc"]
+tags: ["Research assistant", "Research assoicate"]
+---
+
+
+
+In June 2020, I finished up my research assistant positions at UC San Diego’s (UCSD) political science department, and in July, I began working as a research associate for J-PAL’s Payments and Governance Research Program (PGRP), also at UCSD. Now I have been working there for about a month, I wanted to ruminate about the transition from RA to RA.
+Me, being my naive and excitable self, dove head first into PGRP, assuming it to be a full-time version of the work I had been doing for the political science department. A typical workday at the department would go: get tagged in an issue ticket where the task was to create a type of graph, wrangle a dataset in a particular way, or complete a given amount of data-entry. From there, I would spend usually a day or so completing that task, checking-in regularly with my supervisor (either a PhD student or a professor) to clarify questions and arrange next-steps, and then I would move on to the next task. This set up was great for me, quick tasks that usually taught me a new skill–I would be forced to figure out how to make a waffle plot or calculate a certain statistic–and that I could complete in a couple of hours, allowing me to focus on school-related work for the rest of the day. Moreover, I never felt a huge amount of responsibility as I was just working from graph to graph, dataset to dataset, with clear instruction and little room for misunderstanding.
+An aside, I had an absolutely fantastic experience with all the research assistant positions that I held. However, I have colleagues who have had wildly different experiences, and so while this post maintains a warm view toward research assistantships, the darker sides of such positions–not getting paid, being over- and under-worked, workplace misconduct, and the like–need to be acknowledged.
+I enjoyed this style of work, and somewhat foolishly thought that a full-time research associate position would be, in essence, the same. Get given a graph to make or some data to clean or a manuscript to proofread, but all day long. What fun! When you look at the job description for a research assistant and a research associate–in political science and economics at least–they look about the same, and, from my perspective at least, no one ever really distinguished between the two, and so going into my new position, I assumed that, aside from the time commitment, they were the same position.
+In fact, the jump from research assistant to associate was a fairly big one. A lot fo the work is actually quite similar; you spend a lot of time cleaning and analyzing data, making graphs, and so on, but the, for lack of a better word, “vibe”, is entirely different. Perhaps the biggest shock to the system is the self-organization piece. No longer am I being instructed to make a specific graph or clean a specific dataset; it is now my job to define the work agenda, what tasks need doing, and in what order. Of course, there is a PI, a project manager, and usually a few other research associates that allow you to talk through ideas a and get clarity, but for the most part, you are in charge of day-to-day operations. Of course, people will come to you with requests, which I certainly enjoy, though this is not the day-to-day norm. I enumerate a couple of tactics that I have implemented since starting my position later, but for me, the lack of explicit guidance has been the biggest challenge for me, coming from a research assistant position.
+The lack of instruction is exacerbated by the position being full-time. As a part-time researcher, I would intersperse work with my classes and extra-cirriculars, and I wouldn’t usually focus on work-related tasks for more than three hours at a time. Now, I am up at 7, and I work until 4, and I have to fill my entire day with stuff to do!
+Another aside, maybe, in actual fact, the jump from RA to RA is really no big deal, and what actually caused my existential crises was, you know, the big old pandemic that happened at exactly the same time. So I should perhaps say that everything I am saying might want to be taken with a pinch of salt.
+Third, and perhaps more logically, the sheer volume and scope of your responsibilities may be overwhelming at first. You will need to familiarize yourself with vast repositories of data, manuscripts, tracking sheets, instruments; long and complicated variable naming conventions; and code that you will have literally no idea of what it is supposed to do. All of these points are to be expected of any new job, but again, if you were me, going into this with a very rudimentary understanding of the concept of “full-time research”, it can all seem a little overwhelming.
+So, having worked as a research associate for about a month, what have I learned? Firstly, pandemics suck. Secondly, I enumerate a couple of points below that might be of use if you find yourself transitioning between a research assistantship and a research associate position:
+
+- Ask lots of questions
+
+- Obviously, it is good to try to figure things out for yourself, but set a limit on how much time you are going to spend on trying to make sense of something before reaching out to the right person.
+- Additionally, when asking questions or making requests of others, it is good to:
+
+- Enumerate any questions to maintain clarity.
+- Specify a deadline of when you would like them to respond.
+
+- It can also be useful to have a “questions/answers” document to keep record of particular issues. It is useful if you need reminding yourself, or if you end up handing your work off to others.
+
+- Keep a list of things to do
+
+- Try to keep your documents streamlined, and have all of your to dos in one document.
+- Not a popular opinion, but I tend to shy away from using colors/fonts/sizes etc., instead crossing out goals as I complete them.
+- Prioritize in terms of importance, not in terms of how easy something is to achieve.
+
+- Set daily, weekly, and monthly goals
+
+- Again, prioritize the important things. Try not to spend your time working on the small things in order to feel a sense of achievement (I say this, but I also do this literally all of the time).
+- Be honest with yourself and with the task in hand. Based on how other tasks similar to this one have gone, how long do you really think you will need in order to finish it.
+- Hold others accountable, and have others hold you accountable in completing these goals.
+- Sometimes, a task is unexpectedly difficult. If you think it will take longer than planned, and if you promised someone you would get something to them by a deadline, be upfront, clear, and reoganize.
+
+- Document things
+
+- If there is a particular facet of the project that is confusing to you, writing it out can be useful.
+
+- For example, if there is an analysis file that calls in a bunch of other scripts, it could be useful to use an Excel sheet to visualize how all the code files relate to one another. Going further, you could document the inputs into each script, as well as the expected outputs.
+- Where I have a general understanding of something, and I know that the only way I am going to become super comfortable with it is exposure to it, I find documenting, writing about, or visualizing the thing to be very helpful.
+
+- I find using apps like Googlesheets and Googledocs to be the most efficient and the easiest to integrate into my workflow. But as you accrue more and more documents, be them for note-taking, goal-setting, question-answering, and so on, make sure you have a clear and understandable file strucutre.
+
+- I have a folder that is comprised of all documents relating to my work. It is clearly and concisely categorized and fairly easy to navigate. My thought process when creating it was to make something that I could one day hand off to the next research associate for them to use. With that in mind, I think having a folder on all things project related can be very useful for you and for the others you work with.
+
+
+
diff --git a/content/resume.cls b/content/resume.cls
new file mode 100644
index 0000000..e7c4dcd
--- /dev/null
+++ b/content/resume.cls
@@ -0,0 +1,131 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Medium Length Professional CV - RESUME CLASS FILE
+%
+% This template has been downloaded from:
+% http://www.LaTeXTemplates.com
+%
+% This class file defines the structure and design of the template.
+%
+% Original header:
+% Copyright (C) 2010 by Trey Hunner
+%
+% Copying and distribution of this file, with or without modification,
+% are permitted in any medium without royalty provided the copyright
+% notice and this notice are preserved. This file is offered as-is,
+% without any warranty.
+%
+% Created by Trey Hunner and modified by www.LaTeXTemplates.com
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\ProvidesClass{resume}[2010/07/10 v0.9 Resume class]
+
+\LoadClass[11pt,letterpaper]{article} % Font size and paper type
+
+\usepackage[parfill]{parskip} % Remove paragraph indentation
+\usepackage{array} % Required for boldface (\bf and \bfseries) tabular columns
+\usepackage{ifthen} % Required for ifthenelse statements
+
+\pagestyle{empty} % Suppress page numbers
+
+%----------------------------------------------------------------------------------------
+% HEADINGS COMMANDS: Commands for printing name and address
+%----------------------------------------------------------------------------------------
+
+\def \name#1{\def\@name{#1}} % Defines the \name command to set name
+\def \@name {} % Sets \@name to empty by default
+
+\def \addressSep {$\diamond$} % Set default address separator to a diamond
+
+% One, two or three address lines can be specified
+\let \@addressone \relax
+\let \@addresstwo \relax
+\let \@addressthree \relax
+
+% \address command can be used to set the first, second, and third address (last 2 optional)
+\def \address #1{
+ \@ifundefined{@addresstwo}{
+ \def \@addresstwo {#1}
+ }{
+ \@ifundefined{@addressthree}{
+ \def \@addressthree {#1}
+ }{
+ \def \@addressone {#1}
+ }}
+}
+
+% \printaddress is used to style an address line (given as input)
+\def \printaddress #1{
+ \begingroup
+ \def \\ {\addressSep\ }
+ \centerline{#1}
+ \endgroup
+ \par
+ \addressskip
+}
+
+% \printname is used to print the name as a page header
+\def \printname {
+ \begingroup
+ \hfil{\MakeUppercase{\namesize\bf \@name}}\hfil
+ \nameskip\break
+ \endgroup
+}
+
+%----------------------------------------------------------------------------------------
+% PRINT THE HEADING LINES
+%----------------------------------------------------------------------------------------
+
+\let\ori@document=\document
+\renewcommand{\document}{
+ \ori@document % Begin document
+ \printname % Print the name specified with \name
+ \@ifundefined{@addressone}{}{ % Print the first address if specified
+ \printaddress{\@addressone}}
+ \@ifundefined{@addresstwo}{}{ % Print the second address if specified
+ \printaddress{\@addresstwo}}
+ \@ifundefined{@addressthree}{}{ % Print the third address if specified
+ \printaddress{\@addressthree}}
+}
+
+%----------------------------------------------------------------------------------------
+% SECTION FORMATTING
+%----------------------------------------------------------------------------------------
+
+% Defines the rSection environment for the large sections within the CV
+\newenvironment{rSection}[1]{ % 1 input argument - section name
+ \sectionskip
+ \MakeUppercase{\bf #1} % Section title
+ \sectionlineskip
+ \hrule % Horizontal line
+ \begin{list}{}{ % List for each individual item in the section
+ \setlength{\leftmargin}{1.5em} % Margin within the section
+ }
+ \item[]
+}{
+ \end{list}
+}
+
+%----------------------------------------------------------------------------------------
+% WORK EXPERIENCE FORMATTING
+%----------------------------------------------------------------------------------------
+
+\newenvironment{rSubsection}[4]{ % 4 input arguments - company name, year(s) employed, job title and location
+ {\bf #1} \hfill {#2} % Bold company name and date on the right
+ \ifthenelse{\equal{#3}{}}{}{ % If the third argument is not specified, don't print the job title and location line
+ \\
+ {\em #3} \hfill {\em #4} % Italic job title and location
+ }\smallskip
+ \begin{list}{$\cdot$}{\leftmargin=0em} % \cdot used for bullets, no indentation
+ \itemsep -0.5em \vspace{-0.5em} % Compress items in list together for aesthetics
+ }{
+ \end{list}
+ \vspace{0.5em} % Some space after the list of bullet points
+}
+
+% The below commands define the whitespace after certain things in the document - they can be \smallskip, \medskip or \bigskip
+\def\namesize{\huge} % Size of the name at the top of the document
+\def\addressskip{\smallskip} % The space between the two address (or phone/email) lines
+\def\sectionlineskip{\medskip} % The space above the horizontal line for each section
+\def\nameskip{\bigskip} % The space after your name at the top
+\def\sectionskip{\medskip} % The space after the heading section
diff --git a/content/tb.aux b/content/tb.aux
new file mode 100644
index 0000000..f23e546
--- /dev/null
+++ b/content/tb.aux
@@ -0,0 +1 @@
+\relax
diff --git a/content/tb.log b/content/tb.log
new file mode 100644
index 0000000..2cb75b9
--- /dev/null
+++ b/content/tb.log
@@ -0,0 +1,266 @@
+This is pdfTeX, Version 3.14159265-2.6-1.40.20 (MiKTeX 2.9.7250 64-bit) (preloaded format=pdflatex 2020.1.16) 31 JUL 2020 11:40
+entering extended mode
+**./tb.tex
+(tb.tex
+LaTeX2e <2019-10-01> patch level 3
+(resume.cls
+Document Class: resume 2010/07/10 v0.9 Resume class
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\article.cls"
+Document Class: article 2019/10/25 v1.4k Standard LaTeX document class
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\size11.clo"
+File: size11.clo 2019/10/25 v1.4k Standard LaTeX file (size option)
+)
+\c@part=\count80
+\c@section=\count81
+\c@subsection=\count82
+\c@subsubsection=\count83
+\c@paragraph=\count84
+\c@subparagraph=\count85
+\c@figure=\count86
+\c@table=\count87
+\abovecaptionskip=\skip41
+\belowcaptionskip=\skip42
+\bibindent=\dimen102
+)
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/parskip\parskip.st
+y"
+Package: parskip 2020-01-22 v2.0d non-zero parskip adjustments
+
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/oberdiek\kvoptions
+.sty"
+Package: kvoptions 2016/05/16 v3.12 Key value format for package options (HO)
+
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/graphics\keyval.st
+y"
+Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
+\KV@toks@=\toks14
+)
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\ltxcmds
+.sty"
+Package: ltxcmds 2016/05/16 v1.23 LaTeX kernel commands for general use (HO)
+)
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\kvsetke
+ys.sty"
+Package: kvsetkeys 2016/05/16 v1.17 Key value parser (HO)
+
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\infware
+rr.sty"
+Package: infwarerr 2016/05/16 v1.4 Providing info/warning/error messages (HO)
+)
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/oberdiek\etexcmd
+s.sty"
+Package: etexcmds 2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO)
+
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/iftex\ifluatex.s
+ty"
+Package: ifluatex 2019/10/25 v1.5 ifluatex legacy package. Use iftex instead.
+
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/iftex\iftex.sty"
+Package: iftex 2019/11/07 v1.0c TeX engine tests
+)))))
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/etoolbox\etoolbox.
+sty"
+Package: etoolbox 2019/09/21 v2.5h e-TeX tools for LaTeX (JAW)
+\etb@tempcnta=\count88
+))
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/tools\array.sty"
+Package: array 2019/08/31 v2.4l Tabular extension package (FMi)
+\col@sep=\dimen103
+\ar@mcellbox=\box27
+\extrarowheight=\dimen104
+\NC@list=\toks15
+\extratabsurround=\skip43
+\backup@length=\skip44
+\ar@cellbox=\box28
+)
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/base\ifthen.sty"
+Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC)
+))
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/geometry-de\geomet
+ry.sty"
+Package: geometry 2010/09/12 v5.6 Page Geometry
+
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/iftex\ifpdf.sty"
+Package: ifpdf 2019/10/25 v3.4 ifpdf legacy package. Use iftex instead.
+)
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/iftex\ifvtex.sty
+"
+Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
+)
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/generic/iftex\ifxetex.st
+y"
+Package: ifxetex 2019/10/25 v0.7 ifxetex legacy package. Use iftex instead.
+)
+\Gm@cnth=\count89
+\Gm@cntv=\count90
+\c@Gm@tempcnt=\count91
+\Gm@bindingoffset=\dimen105
+\Gm@wd@mp=\dimen106
+\Gm@odd@mp=\dimen107
+\Gm@even@mp=\dimen108
+\Gm@layoutwidth=\dimen109
+\Gm@layoutheight=\dimen110
+\Gm@layouthoffset=\dimen111
+\Gm@layoutvoffset=\dimen112
+\Gm@dimlist=\toks16
+
+("C:\Users\tbrai\AppData\Local\Programs\MiKTeX 2.9\tex/latex/geometry\geometry.
+cfg")) (tb.aux)
+\openout1 = `tb.aux'.
+
+LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 33.
+LaTeX Font Info: ... okay on input line 33.
+LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 33.
+LaTeX Font Info: ... okay on input line 33.
+LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 33.
+LaTeX Font Info: ... okay on input line 33.
+LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 33.
+LaTeX Font Info: ... okay on input line 33.
+LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 33.
+LaTeX Font Info: ... okay on input line 33.
+LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 33.
+LaTeX Font Info: ... okay on input line 33.
+
+*geometry* driver: auto-detecting
+*geometry* detected driver: pdftex
+*geometry* verbose mode - [ preamble ] result:
+* driver: pdftex
+* paper:
+* layout:
+* layoutoffset:(h,v)=(0.0pt,0.0pt)
+* modes:
+* h-part:(L,W,R)=(36.135pt, 542.02501pt, 36.135pt)
+* v-part:(T,H,B)=(36.135pt, 722.7pt, 36.135pt)
+* \paperwidth=614.295pt
+* \paperheight=794.96999pt
+* \textwidth=542.02501pt
+* \textheight=722.7pt
+* \oddsidemargin=-36.135pt
+* \evensidemargin=-36.135pt
+* \topmargin=-73.135pt
+* \headheight=12.0pt
+* \headsep=25.0pt
+* \topskip=11.0pt
+* \footskip=30.0pt
+* \marginparwidth=59.0pt
+* \marginparsep=10.0pt
+* \columnsep=10.0pt
+* \skip\footins=10.0pt plus 4.0pt minus 2.0pt
+* \hoffset=0.0pt
+* \voffset=0.0pt
+* \mag=1000
+* \@twocolumnfalse
+* \@twosidefalse
+* \@mparswitchfalse
+* \@reversemarginfalse
+* (1in=72.27pt=25.4mm, 1cm=28.453pt)
+
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <10.95> on input line 33.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <8> on input line 33.
+LaTeX Font Info: External font `cmex10' loaded for size
+(Font) <6> on input line 33.
+
+Overfull \hbox (30.0pt too wide) in paragraph at lines 33--33
+[]
+ []
+
+
+! LaTeX Error: Something's wrong--perhaps a missing \item.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H for immediate help.
+ ...
+
+l.94 \end{rSubsection}
+
+Try typing to proceed.
+If that doesn't work, type X to quit.
+
+
+! LaTeX Error: Something's wrong--perhaps a missing \item.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H for immediate help.
+ ...
+
+l.98 \end{rSubsection}
+
+Try typing to proceed.
+If that doesn't work, type X to quit.
+
+[1
+
+{C:/Users/tbrai/AppData/Local/MiKTeX/2.9/pdftex/config/pdftex.map}]
+
+! LaTeX Error: Something's wrong--perhaps a missing \item.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H for immediate help.
+ ...
+
+l.147 \item B
+ eginner: Python, Tableau.
+Try typing to proceed.
+If that doesn't work, type X to quit.
+
+
+! LaTeX Error: Something's wrong--perhaps a missing \item.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H for immediate help.
+ ...
+
+l.147 \item B
+ eginner: Python, Tableau.
+Try typing to proceed.
+If that doesn't work, type X to quit.
+
+
+! LaTeX Error: Something's wrong--perhaps a missing \item.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H for immediate help.
+ ...
+
+l.147 \item B
+ eginner: Python, Tableau.
+Try typing to proceed.
+If that doesn't work, type X to quit.
+
+
+! LaTeX Error: Something's wrong--perhaps a missing \item.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H for immediate help.
+ ...
+
+l.148 \end{rSubsection}
+
+Try typing to proceed.
+If that doesn't work, type X to quit.
+
+[2] (tb.aux) )
+Here is how much of TeX's memory you used:
+ 1597 strings out of 492484
+ 23003 string characters out of 3121601
+ 98141 words of memory out of 3000000
+ 5960 multiletter control sequences out of 15000+200000
+ 7639 words of font info for 27 fonts, out of 3000000 for 9000
+ 1141 hyphenation exceptions out of 8191
+ 59i,4n,32p,870b,176s stack positions out of 5000i,500n,10000p,200000b,50000s
+
+Output written on tb.pdf (2 pages, 88399 bytes).
+PDF statistics:
+ 33 PDF objects out of 1000 (max. 8388607)
+ 0 named destinations out of 1000 (max. 500000)
+ 1 words of extra memory for PDF output out of 10000 (max. 10000000)
+
diff --git a/content/tjbrailey_resume_2020_academic.pdf b/content/tb.pdf
similarity index 54%
rename from content/tjbrailey_resume_2020_academic.pdf
rename to content/tb.pdf
index 637317edd911ecd5da5b0c06410c04bac62239dd..00c4e5b93937fcacb0c68465d158f901770c90d0 100644
GIT binary patch
delta 40994
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
Comments
+Lastly, and more generally, a good piece of reproducible code will have lots of comments. I enumerate a few key points below:
++
+
+
+
+
+
+For each chunk, i.e. each for loop, ggplot, function, etc., have a header comment outlining what exactly it does.
Then, for each line of code, have an in-line comment that states what that code does. Are we taking the log of a variable? Are we replacing values that equal -99 with NA? While keeping this concise and short, it is also often useful to include a note on why you are doing that thing, too. An explanation of why can also come at the start of the chunk in order to avoid cluttering the code itself.
Avoid comments that superfluous/humorous/otherwise unnecessary. If, when you read back through the code, you realize that a comment doesn’t add to the overall clarity of your code, then it is best to delete it.
Avoid abbreviations. It’s better for the comments to be a bit longer and be very clear than shorter and hard to decipher.
At the end of a chunk of code, if applicable, have a note on what should have been produced. For example, if you have a for loop that creates a bunch of new variables, state how many new variables should have been created, their class, their naming format, and their purpose. While one could reasonably ascertain what the code is doing, and figure out what the output would do, it is better to have it in writing to avoid any unnecessary confusion and time-wasting.
I tend to use these commenting conventions for all pieces of code that I write, from analysis and cleaning scripts, to user-defined functions, and so on.
+