Skip to content

Instantly share code, notes, and snippets.

@mattbaggott
Last active July 9, 2021 15:37
Show Gist options
  • Save mattbaggott/4361381 to your computer and use it in GitHub Desktop.
Save mattbaggott/4361381 to your computer and use it in GitHub Desktop.
Sample code to demonstrate some ways of making circular time-of-day plots in R (i.e. polar plots with 24 major hourly units)
##
## Sample code to demonstrate circular time plots in R
## matt@baggott.net
## Dec 22, 2012
# inspired by
# http://stackoverflow.com/questions/2076370/most-underused-data-visualization
library(lubridate)
library(circular)
library(ggplot2) # use at least 0.9.3 for theme_minimal()
## generate random data in POSIX date-time format
N=500
events <- as.POSIXct("2011-01-01", tz="GMT") +
days(floor(365*runif(N))) +
hours(floor(24*rnorm(N))) + # using rnorm here
minutes(floor(60*runif(N))) +
seconds(floor(60*runif(N)))
# extract hour with lubridate function
hour_of_event <- hour(events)
# make a dataframe
eventdata <- data.frame(datetime=events, eventhour=hour_of_event)
# determine if event is in business hours
eventdata$Workday<-eventdata$eventhour%in%seq(9,17)
## first method of plotting is from ggplot2
ggplot(eventdata,aes(x=eventhour,fill=Workday))+
geom_histogram(breaks=seq(0,24),width = 2,colour="grey")+
coord_polar(start=0)+
theme_minimal()+
scale_fill_brewer()+
ylab("Count")+
ggtitle("Events by Time of day")+
scale_x_continuous("", limits=c(0,24),
breaks=seq(0,24),
labels=seq(0,24))
## two remaining examples use package::circular
## first is plot.circular(), second is roseplot()
# make circular class from package circular
eventdata$eventhour <- circular(hour_of_event%%24, # convert to 24 hrs
units="hours", template="clock24")
# plot events on a circle
plot.circular(eventdata$eventhour, stack=TRUE, shrink=2, cex=0.7,col="red")
# estimate density, class is still circular not density
bw <- bw.nrd0(eventdata$eventhour) # may not be best method: experiment
dens <- density.circular(eventdata$eventhour, bw=bw) #bw must be given
# plot.density.circular is not useful for large numbers of events
# or we have a bad bandwidth -- need to determine better method
plot(dens,plot.type="circle", join=TRUE, shrink=1.3, cex=0.5, col="blue")
# plot.density on type = "line" is better, but bw still questionable
plot(dens, plot.type="line", join=TRUE, cex=0.5, col="blue")
# plot a rose diagram, default looks bad
rose.diag(eventdata$eventhour, bin=24, col="blue",
main="Events by Hour (sqrt scale)")
# change prop argument, now looks better
rose.diag(eventdata$eventhour, bin=24, col="blue",
main="Events by Hour (sqrt scale)", prop=3)
# linear scale will emphasize outliers, need to change prop more
rose.diag(eventdata$eventhour, bin=24, col="blue",
main="Events by Hour (linear scale)", prop=10,
radii.scale = "linear")
# plot sqrt and linear side by side
oldpar <- par()
par(mfcol=c(1, 2))
rose.diag(eventdata$eventhour, bin=24, col="blue", cex = 0.5,
main="Sqrt scale", prop=3)
rose.diag(eventdata$eventhour, bin=24, col="blue", cex = 0.5,
main="Linear scale", prop=10,
radii.scale = "linear")
par(oldpar)
# redundantly add points to surface
# need to adjust parameters like shrink, cex, and prop
rp <- rose.diag(eventdata$eventhour, bin=24, col="blue",
main="Events by Hour (linear scale)", prop=12,
radii.scale = "linear", shrink=2, cex=0.5)
points(eventdata$eventhour, plot.info=rp, col="purple",stack=TRUE)
## in addition to what is in circular
## library(psych) has helpful circular statistics.
## circadian.mean(): circular mean
## circadian.cor(): circular (phasic) correlations
## circadian.linear.cor(): correlation between linear variables and circular variables
## cosinor(): fit phase angle for measures taken with a fixed period (e.g., 24 hours)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment