When encountering a data set for the first time, it is often a good idea to explore the distribution of each variable.
Here is a simple R function that will create a nice display to aid in exploring the univariate distribution of a numeric vector.
For example, using the USArrests dataset:
data(USArrests) eda.plots(USArrests$Murder, "Murder arrests (per 100,000)")
Source code for the eda.plots function:
#--------------------------------------------------------------------
# Univariate Exploratory Data Analysis
#--------------------------------------------------------------------
# PANELS
#--------------------------------------------------------------------
# (1) Top Left: Histogram
# (2) Top Right: Boxplot
# (3) Bottom Left: Density Plot
# (4) Bottom Right: Normal QQ-Plot
#--------------------------------------------------------------------
# ARGUMENT | INPUT | DESCRIPTION
#--------------------------------------------------------------------
# x | numeric vector | variable to be analyzed
# vname | character vector | variable label & filename
# outdir | character vector | output directory
# dev | character vector | graphics device
# overwrite | logical vector | overwrite existing files or not
# col | character vector | color of graph elements
#--------------------------------------------------------------------
eda.plots <- function(x,
vname="edaplots",
outdir="./",
dev="png",
overwrite=TRUE,
col="black") {
## check inputs
if(is.vector(x) && class(x)!="numeric") {
stop("x is not a numeric vector\n")
} else {
stop("x is not a vector\n")
}
char.vars <- c(vname,outdir,dev,col)
for(v in char.vars) {
if(class(v)=="character") {
if(nchar(v)>50)
stop(sprintf("%s is too long",v))
if(length(v)>1) {
v <- v[1]
warning(sprintf("%s has been coerced to its first element",v))
}
} else {
stop(sprintf("%s is not a character vector",v))
}
}
if(class(overwrite)=="logical") {
if(length(overwrite)>1) {
overwrite <- overwrite[1]
warning(sprintf("%s has been coerced to its first element",v))
}
} else {
stop("overwrite is not a logical vector")
}
## create directory if needed
dir.create(file.path(outdir), showWarnings=FALSE)
fname <- gsub("[[:blank:][:punct:]]", "", vname)
plot.name <- sprintf("%s/%s.%s", outdir, tolower(fname), tolower(dev))
if(!overwrite) {
if(any(grepl(plot.name,dir())))
stop(sprintf("%s currently exists already and will not be overwritten",
plot.name))
}
## plots
# set up layout
do.call(tolower(dev), list(plot.name))
par(mfrow=c(2,2), mai=c(0.75, 0.75, 0.25, 0.25))
# mai=c(bottom,left,top,right)
# graph parameters
cex.axis <- 1.25
cex.lab <- 1.5
cex <- 1.5
lwd <- 2
# histogram - top left panel
h.col <- ifelse(col=="black", "white", col)
hist(x,
col=h.col,
lwd=lwd,
main="",
xlab="",
cex.axis=cex.axis,
cex.lab=cex.lab
)
# boxplot - top right panel
b.col <- ifelse(col=="black", "white", col)
boxplot(x,
horizontal=TRUE,
lwd=lwd,
col=b.col,
ylab=vname,
cex.axis=cex.axis,
cex.lab=cex.lab
)
# densityplot - bottom left panel
plot(density(x),
col=col,
lwd=lwd,
main="",
xlab="",
cex.axis=cex.axis,
cex.lab=cex.lab
)
rug(x, col=col)
# QQ - bottom right panel
qqnorm(x,
col=col,
cex=cex,
lwd=lwd,
main="",
cex.axis=cex.axis,
cex.lab=cex.lab
)
qqline(x)
dev.off()
invisible()
}



