# Write your code hereWeek 4 Tutorial
Visualizing Data
First things first: Make a new project in RStudio, and be sure to place it somewhere where you can easily find it (e.g., Documents, Desktop). Then download this file (the .qmd file) from the syllabus website and place it in the folder associated with that project. Then open this file in RStudio and follow along.
I encourage you to work with/talk to others throughout this tutorial, especially during times where I have you code on your own and use AI. When you code, think about the SPARCK framework:
S: Set up (What is your end goal?)
P: Pseudocode (What are the steps?)
A: AI (What are your AI prompts?)
R: Run (Run it!)
C: Check (Did your code work?)
K: Knowledge (What does your code mean?)
Agenda
Exploring our data
The grammar of graphics
ggplotsyntaxTypes of graphs
Polishing your graphs
Practice
Exploring our data
For today’s tutorial, we’re going to use a dataset from the NYPD on Stop and Frisk. Search “stop and frisk” on NYC Open Data, then download the Excel file for 2025 from the NYPD website. Put the data in your folder for this tutorial. Then, load the data in. (Hint: Since this is an excel file, and not a csv file, you’ll need to load a package called readxl (this is already installed from when you installed tidyverse), and then use the read_excel() function.)
Before we get started visualizing, you should explore the data a bit. What are some things you notice about it? What are some interesting variables?
Answer:
There are a few things you might notice that we need to immediately do to clean this data and make it a bit more usable:
Clean the names of the columns using the
clean_names()function from thejanitorpackageTurn all the
(null)values toNA, which is how R signifies missing data.There is a variable called
stop_duration_minutesthat has some values that are over 10 hours long. Those are probably mistakes. Get rid of those rows so they don’t mess up our averages later on.There are 8 people whose age wasn’t recorded (
NA). We’ll be graphing age a lot, so get rid of those rows too.
Go ahead and clean the data now. You may encounter code from AI when cleaning that you haven’t seen before. That’s okay! Just make sure you a) check that it worked correctly, and b) that you have a basic understanding of what it’s doing.
# Write your code hereThe grammar of graphics
Today’s lesson is rooted in the data visualization theory known as the grammar of graphics (Wilkinson, 2005), developed by Leland Wilkinson. The description below is adapted from Ismay et al. (2025).
At their most basic, graphics/plots/charts (we’ll use these terms interchangeably) provide a nice way to explore the patterns in data, such as the presence of outliers, distributions of individual variables, and relationships between groups of variables. Graphics are designed to emphasize the findings and insights you want your audience to understand. This does, however, require a balancing act. On the one hand, you want to highlight as many interesting findings as possible. On the other hand, you don’t want to include so much information that it overwhelms your audience.
As we will see, plots also help us to identify patterns and outliers in our data. We’ll see that a common extension of these ideas is to compare the distribution of one numerical variable, such as what are the center and spread of the values, as we go across the levels of a different categorical variable.
We start with a discussion of a theoretical framework for data visualization known as “the grammar of graphics.” Think of how we construct and form sentences in English by combining different elements, like nouns, verbs, articles, subjects, objects, etc. We can’t just combine these elements in any arbitrary order; we must do so following a set of rules known as a linguistic grammar. Similarly to a linguistic grammar, “the grammar of graphics” defines a set of rules for constructing statistical graphics by combining different types of layers.
In short, the grammar tells us that:
A statistical graphic is a
mappingofdatavariables toaesthetic attributes ofgeometric objects.
Specifically, we can break a graphic into the following three essential components:
data: the dataset containing the variables of interest.geom: the geometric object in question. This refers to the type of object we can observe in a plot. For example: points, lines, and bars.aes: aesthetic attributes of the geometric object. For example, x/y position, color, shape, and size. Aesthetic attributes are mapped to variables in the dataset.
How does this translate to coding in R? Basically, when we make visualizations in R, we need to do three things to make a basic plot:
Tell our visualization package what our data is (
data)Tell our visualization package what relationships we want to see (
aes)Tell our visualization package how we want to see those relationships (
geom)
ggplot syntax
The visualization package that most scientists use to make graphs in R is called ggplot. The gg stands for “grammar of graphics,” meaning that this package operates according to that grammar we laid out earlier. Let’s build our first graph piece by piece so we can see how it all comes together.
First, what happens if we just tell ggplot() the data we want to use?
# Write your code hereNothing! Remember, we need to tell ggplot three things in order to get a basic graph. Let’s next tell it what relationships we want to see. Specifically, let’s say we want to see the spread of ages of people who are stopped.
# Write your code hereA little better! But still nothing interesting. Let’s now tell it how we want to see the relationships by specifying the type of graph. Let’s visualize the spread of ages using a histogram.
# Write your code hereHooray! We made a graph! It’s ugly, but it’s visualizing real information that we can report on. Around what age is most commonly stopped?
Answer:
The above code - in which we specify our data, our aesthetics, and a geometric object - forms the basis of every graph we will make in this class.
Types of graphs
There are many kinds of graphs we can make in ggplot, many of them beginning with geom_. You can see the full list here. Each type of graph comes with its own options to consider and customize the graph. Let’s go through a few of the most important ones.
Histogram
The graph we just made was a histogram. One important way we might wish to customize the way the data is shown is by how many “bins” there are. In this case, a “bin” is just a bar - our data are grouped into bars with specific ranges of values to calculate the counts. Use the bins = argument to make a graph with a different number of bins. (The default is 30).
# Write your code hereLet’s make this graph a bit more aesthetically pleasing! Add some color using the color = and fill = arguments. You can see a list of named colors in R here.
# Write your code hereBox plot
Another useful type of graph to visualize the spread of your data is the boxplot. What’s nice about ggplot and using a grammar of graphics is that if you want to display the same data in a different format, the only part of your code you need to change is where you specify the geom.
Use geom_boxplot() to display the spread of ages across the entire dataset, with the age variable on the x axis.
# Write your code hereThis shows the median age of person who is stopped (the thick line), the 75th and 25th percentiles (top and bottom of box), all data within 1.5x the interquartile range (the whiskers), and data outside of that range aka outliers (the dots).
Any guesses how we can get this to display the box vertically, which is how boxplots are typically displayed?
# Write your code hereSo this plot is showing the spread of our data across the entire dataset. But often, boxplots are useful because they allow us to compare data distributions for different categories in our data. In order to do this, we need to add an additional aesthetic, because we need to specify an additional axis.
Make a boxplot that shows the spread of age stopped, broken down by sex.
# Write your code hereNow we can start to derive some insights from our data! We can see that the median age for men who are stopped is lower than the median age for women.
There are a bunch more ways we can customize a boxplot. You can type ?geom_boxplot() in the console to see the full list of options.
Make a new version of that same graph where you specify the color and shape of the outliers, whisker, and box.
# Write your code hereBar plot
There are two ways to make bar graphs in ggplot: geom_bar() and geom_col(). They have slightly different use cases based on the structure of your data:
geom_bar()calculates counts based on your raw datageom_col()expects your data to already be summarized and takes raw numbers in your data
Our data here is not pre-counted. Use geom_bar() to display a bar graph of the number of stops in each borough.
# Write your code heregeom_bar() defaults to “count” as the summary variable of interest, but you can specify any summary variable you’re interested in by providing additional arguments. For example, use geom_bar() to make a bar graph that shows the average age of people stopped, by borough. (You’ll have to add an additional aesthetic.)
# Write your code hereAnother very useful aspect of bar graphs is to display multiple categories for each x axis value. For example, let’s say you wanted to show the average stop length in each borough, broken down by sex.
This is going to require you to specify an additional aesthetic, which is the variable by which the bars should be filled in. This is different from what we did earlier when we specified a specific color as an argument within the geom. Now, color (or in this case, fill =) is an aesthetic, because it conveys information.
Then, we use the position = 'dodge' argument within geom_bar() to make the bars display next to each other.
Use position = 'dodge' to make a bar graph that shows average stop length by borough, with different colored bars by sex.
# Write your code hereMake this graph cleaner by getting rid of datapoints where borough is not recorded (NA).
# Write your code hereScatterplots
Scatterplots are very useful for showing relationships between two continuous variables. There are two geoms you might want to use to make a scatter plot. First, use geom_point() to graph the relationship between stop duration and age.
# Write your code hereOkay, there’s some sort of pattern here, where we can see that older people who are stopped tend to have shorter stops. But it’s hard to see what’s going on with our data exactly. There are two things we should do to make our data clearer.
First, let’s use geom_jitter() instead of geom_point(), which “jitters” the true value of our data when plotting, so that a bunch of data points with the same value aren’t stacked on top of each other.
# Write your code hereSee how the dots are a little less lined up than they were before?
Next, we need to use the alpha = argument, which specifies how transparent our dots are. This allows us to see where data is “denser” because the dots will be darker. Make the above plot but with the alpha = .1 argument.
# Write your code hereLine graph
The best use of line graphs is probably for showing effects over time. This means that your x axis is most likely going to be some sort of time variable.
Create a line graph that shows the number of stops each day of the year. This will require several steps, including
Creating a new variable that converts your date column to a formal “datetime” data type
Summarizing it so you have a count of the number of stops each day
Graphing a line graph with
geom_line()
(Hint: The above is basically pseudocode! It’s good to get used to thinking about coding like the above.)
# Write your code hereCombining plots
What’s great about ggplot is that you can combine multiple plots in one graph. For example, let’s make the above graph but with points added in using geom_point().
# Write your code hereA useful way of combining multiple graphs is to show a summary and the raw data at the same time.
Make a bar graph (using geom_bar()) that shows the average age of stops by borough, with raw data included using geom_jitter().
# Write your code hereYikes, that looks horrible. Adjust the alpha of the points to .1, and use the width = argument so that the dots are not jittered as widely (I’d recommend .1). And give it some color! (Make the bars and dots different colors.)
# Write your code herePolishing your graphs
Congratulations on being a plotter extraordinaire!
But here’s the thing. There’s actually a TON more types of layers that ggplot can add to improve the look of your graph. I’ll go over a few basics here.
First is the labels, using the labs() function. This allows you to specify your labels nicely. Make the above graph but with a clearly labeled X axis, Y axis, and title.
# Write your code hereYou can also change the way the background looks by specifying the theme_. My favorites are theme_bw() and theme_classic(). You can find the full list here. Try one below.
# Write your code hereYou might also want to make all of your font bigger. In fact, the default font size in ggplot graphs is way too small for a presentation. Make a version of your graph where everything has a bigger font below.
# Write your code hereIf you find that doing this makes the text of your x axis overlap, you can adjust the angle of the text.
# Write your code hereBasically, you have complete control over what your graph looks like in ggplot. You should familiarize yourself with all of the options so that you can describe to AI exactly what you’d like to change, and how.
There are several topics that we didn’t cover in this tutorial, such as color palettes and facetting. We’ll encounter these in our “advanced visualization” tutorial, or you may encounter them on your own before then.
Saving your graphs
One more thing! If you make a beautiful graph, you’ll likely want to save it. You can do that using the ggsave() function. If you call it right after displaying your graph, it will save whatever is displayed. You just need to specify the name of the file you want it saved to.
# Write your code herePractice
AI can help you create graphs, but it’s less helpful at figuring out what the most exciting datapoints are that you want to visualize. This is where you - as a thinking, creative budding young scientist and human - come in.
Make your own graph below, using SPARCK. It can be any graph type you want. It has to involve at least one column that we haven’t used yet in this tutorial. Show us something interesting! It’s okay if you need to do some cleaning or summarizing on your data before creating the graph.
S:
P:
A:
R:
# Write your code hereC:
K:
References
Ismay, C., Kim, A. Y., & Valdivia, A. (2025). The grammar of graphics. In Statistical inference via data science: A ModernDive into R and the tidyverse (2nd ed., Section 2.1). https://moderndive.com/v2/02-visualization.html
Wilkinson, L. (2005). The grammar of graphics (2nd ed.). Springer.