Last active
July 9, 2021 15:37
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
## Sample code to demonstrate circular time plots in R | |
## [email protected] | |
## 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