There are a lot of ways to show distributions, but for the purposes of this tutorial, I'm only going to cover the more traditional plot types like histograms and box plots. Otherwise, we could be here all night. Plus the basic distribution plots aren't exactly well-used as it is.
Before you get into plotting in R though, you should know what I mean by distribution. It's basically the spread of a dataset. For example, the median of a dataset is the half-way point. Half of the values are less than the median, and the other half are greater than. That's only part of the picture.
What happens in between the maximum value and median? Do the values cluster towards the median and quickly increase? Are there are lot of values clustered towards the maximums and minimums with nothing in between? Sometimes the variation in a dataset is a lot more interesting than just mean or median. Distribution plots help you see what's going on.
Want more? Google and Wikipedia are your friend.Anyways, that's enough talking. Let's make some charts.
If you don't have R installed yet, .
Box-and-Whisker Plot
This old standby was created by statistician John Tukey in the age of graphing with pencil and paper. I wrote on how to read them a while back, but you basically have the median in the middle, upper and lower quartiles, and upper and lower fences. If there are outliers more or less than 1.5 times the upper or lower quartiles, respectively, they are shown with dots.
The method might be old, but they still work for showing basic distribution. Obviously, because only a handful of values are shown to represent a dataset, you do lose the variation in between the points.
To get started, load the data in R. You'll use state-level crime data from the .
# Load crime datacrime <- read.csv("http://datasets.flowingdata.com/crimeRatesByState-formatted.csv")
Remove the District of Columbia from the loaded data. Its city-like makeup tends to throw everything off.
# Remove Washington, D.C.crime.new <- crime[crime$state != "District of Columbia",]
Oh, and you don't need the national averages for this tutorial either.
# Remove national averagescrime.new <- crime.new[crime.new$state != "United States ",]
Now all you have to do to make a box plot for say, robbery rates, is plug the data into boxplot()
.
# Box plotboxplot(crime.new$robbery, horizontal=TRUE, main="Robbery Rates in US")
Want to make box plots for every column, excluding the first (since it's non-numeric state names)? That's easy, too. Same function, different argument.
# Box plots for all crime ratesboxplot(crime.new[,-1], horizontal=TRUE, main="Crime Rates in US")
Multiple box plot for comparision.
Histogram
Like I said though, the box plot hides variation in between the values that it does show. A histogram can provide more details. Histograms look like bar charts, but they are not the same. The horizontal axis on a histogram is continuous, whereas bar charts can have space in between categories.
Just like boxplot()
, you can plug the data right into the hist()
function. The breaks
argument indicates how many breaks on the horizontal to use.
# Histogramhist(crime.new$robbery, breaks=10)
Look, ma! It's not a a bar chart.
Using the hist()
function, you have to do a tiny bit more if you want to make multiple histograms in one view. Iterate through each column of the dataframe with a for loop. Call hist()
on each iteration.
# Multiple histogramspar(mfrow=c(3, 3))colnames <- dimnames(crime.new)[[2]]for (i in 2:8) { hist(crime[,i], xlim=c(0, 3500), breaks=seq(0, 3500, 100), main=colnames[i], probability=TRUE, col="gray", border="white")}
Using the same scale for each makes it easy to compare distributions.
Density Plot
For smoother distributions, you can use the density plot. You should have a healthy amount of data to use these or you could end up with a lot of unwanted noise.
To use them in R, it's basically the same as using the hist()
function. Iterate through each column, but instead of a histogram, calculate density, create a blank plot, and then draw the shape.
# Density plotpar(mfrow=c(3, 3))colnames <- dimnames(crime.new)[[2]]for (i in 2:8) { d <- density(crime[,i]) plot(d, type="n", main=colnames[i]) polygon(d, col="red", border="gray")}
Multiple filled density plots.
You can also use histograms and density lines together. Instead of plot()
, use hist()
, and instead of drawing a filled polygon()
, just draw a line.
# Histograms and density linespar(mfrow=c(3, 3))colnames <- dimnames(crime.new)[[2]]for (i in 2:8) { hist(crime[,i], xlim=c(0, 3500), breaks=seq(0, 3500, 100), main=colnames[i], probability=TRUE, col="gray", border="white") d <- density(crime[,i]) lines(d, col="red")}
Histogram and density, reunited, and it feels so good.
Rug
The rug, which simply draws ticks for each value, is another way to show distributions. It usually accompanies another plot though, rather than serve as a standalone. Simply make a plot like you usually would, and then use rug()
to draw said rug.
# Density and rugd <- density(crime$robbery)plot(d, type="n", main="robbery")polygon(d, col="lightgray", border="gray")rug(crime$robbery, col="red")
Using a rug under a density plot.
Violin Plot
The violin plot is like the lovechild between a density plot and a box-and-whisker plot. There's a box-and-whisker in the center, and it's surrounded by a centered density, which lets you see some of the variation.
# Violin plotlibrary(vioplot)vioplot(crime.new$robbery, horizontal=TRUE, col="gray")
I bet this violin sounds horrible.
Bean Plot
The bean plot takes it a bit further than the violin plot. It's something of a combination of a box plot, density plot, and a rug in the middle. I've never actually used this one, and I probably never will, but there you go.
# Bean plotlibrary(beanplot)beanplot(crime.new[,-1])
A little too busy for me, but here you go.
Wrapping Up
If you take away anything from this, it should be that variance within a dataset is worth investigating. Picking out single datapoints or only using medians is the easy thing to do, but it's usually not the most interesting.