I have some data that I would like to 1) plot as grouped boxplots, and 2) add significance bars A) between boxplots within each group and B) between specific boxplots of different groups. My data looks something like this:
library("ggplot2")
df <- data.frame(enzyme = c(rep("A", 9), rep("B", 9), rep("C", 9)),
substrate = c(rep("1", 3), rep("2", 3), rep("3", 3),
rep("1", 3), rep("4", 3), rep("5", 3),
rep("1", 3), rep("4", 3), rep("5", 3)),
AUC = c(6.64, 6.56, 6.21, 5.96, 6.12, 6.24, 6.02, 6.32, 6.12,
0, 0, 0, 5.99, 6.26, 5.94, 0, 0, 0,
0, 0, 0, 5.99, 6.11, 6.13, 0, 0, 0))
q <- ggplot(df, aes(x = enzyme, y = AUC, color = substrate)) +
geom_boxplot(show.legend = F,
position = position_dodge2(width = 0.75, preserve = "single")) +
geom_point(show.legend = F, size = 2, position = position_dodge2(width = 0.75, preserve = "single"))
plot(q)
I know that I can add significance bars between groups with the following:
q + geom_signif(comparisons = list(c("A", "B"), c("A", "C"), c("B", "C")),
test = "t.test", map_signif_level = T)
However, these comparisons are not meaningful for my data.
Instead, I would like to A) add significance bars between boxplots of the same group. I thought I could follow the suggestion of Simon, who suggested that I manually add bars by defining p-values, labels, and y coordinates for the bars (How to add significance bar between subgroups of box plot), though for my dataset this will be more difficult because I have three subgroups per group rather than two.
Ultimately, I would also like to B) add significance bars comparing two specific subgroups from different groups.
My question is, is there any easy way to do this using existing functions/packages? If I have to do this manually, can anyone suggest a good strategy? I would appreciate it!
I thought about this for a bit and figured out a lengthy solution. If anyone has a more succinct way of doing this, please let me know!
## significance bars within and between subgroups
# rearrange df, one unique sample per column, rows are replicates
df.split <- do.call(cbind, sapply(split(df, df$enzyme), function(x) {
sapply(split(x, x$substrate), function(x) {x$AUC}) }) )
# keep track of sample names
sample.names <- do.call(c, lapply(split(df, df$enzyme), function(x) {
unique(paste0(x$enzyme, ".", x$substrate)) }) )
colnames(df.split) <- sample.names
# perform statistical tests between every pairwise combination of
# samples/columns in df.split
df.tests <- apply(combn(seq_along(sample.names), 2), 2,
function(x) {
t.test(df.split[ ,x[1]], df.split[ ,x[2]])$p.value })
# keep track of sample pairs
sample.pairs <- apply(combn(seq_along(sample.names), 2), 2,
function(x) {
paste0(colnames(df.split)[x[1]], "X",
colnames(df.split)[x[2]]) })
names(df.tests) <- sample.pairs
# think about how the significance bars will be laid out: because there are
# three subgroups per enzyme, the bars for the three pairwise comparisons on
# the same plot would overlap. This needs to be done in layers
# select tests of interest for each layer
within.tests.1 <- c("A.1XA.2", "A.2XA.3",
"B.1XB.4", "B.4XB.5",
"C.1XC.4", "C.4XC.5")
within.tests.2 <- c("A.1XA.3", "B.1XB.5","C.1XC.5")
between.tests.1 <- c("A.1XB.4", "B.4XC.4")
between.tests.2 <- c("A.1XC.4")
p.values.1 <- df.tests[which(names(df.tests) %in% within.tests.1)]
p.values.2 <- df.tests[which(names(df.tests) %in% within.tests.2)]
p.values.3 <- df.tests[which(names(df.tests) %in% between.tests.1)]
p.values.4 <- df.tests[which(names(df.tests) %in% between.tests.2)]
# convert p-values into easily read labels, with NaN values omitted
p.values.1 <- replace(p.values.1, is.na(p.values.1), 1)
p.values.2 <- replace(p.values.2, is.na(p.values.2), 1)
p.values.3 <- replace(p.values.3, is.na(p.values.3), 1)
p.values.4 <- replace(p.values.4, is.na(p.values.4), 1)
labels.1 <- symnum(p.values.1, corr = FALSE, cutpoints = c(0, .001,.01,.05, 1),
symbols = c("***","**","*",""))
labels.2 <- symnum(p.values.2, corr = FALSE, cutpoints = c(0, .001,.01,.05, 1),
symbols = c("***","**","*",""))
labels.3 <- symnum(p.values.3, corr = FALSE, cutpoints = c(0, .001,.01,.05, 1),
symbols = c("***","**","*",""))
labels.4 <- symnum(p.values.4, corr = FALSE, cutpoints = c(0, .001,.01,.05, 1),
symbols = c("***","**","*",""))
# determine coordinates for significance bars
# y values for layer 1 should all be just above the highest data point of all
# samples being compared
y.values.1 <- do.call(max, lapply(unlist(strsplit(names(labels.1), "X")),
function(x) {
df.split[, which(colnames(df.split) %in% x)] }) ) + 0.3 %>%
rep(times = length(labels.1))
# y values for layer 2 should be higher than those of layer 1
y.values.2 <- y.values.1[c(1, 3, 5)] + 0.4
# y values for layer 3 should all be above the highest data point of all
# samples being compared, and higher than layer 2
y.values.3 <- do.call(max, lapply(unlist(strsplit(names(labels.3), "X")),
function(x) {
df.split[, which(colnames(df.split) %in% x)] }) ) + 1.2 %>%
rep(times = length(labels.3))
# y values for layer 4 should be higher than those of layer 3
y.values.4 <- y.values.3[1] + 0.5
# for x values, first boxplot is always at x = 1
# since there are three groups per x = 1 and preserve = "single", the width of
# each subgroup boxplot is 0.25
x.min.values.1 <- c(0.75, 1, 1.75, 2, 2.75, 3)
x.max.values.1 <- x.min.values.1 + 0.25
x.min.values.2 <- c(0.75, 1.75, 2.75)
x.max.values.2 <- x.min.values.2 + 0.50
x.min.values.3 <- c(0.75, 2)
x.max.values.3 <- c(2, 3)
x.min.values.4 <- c(0.75)
x.max.values.4 <- c(3)
# finally, plot the significance bars for each layer, one on top of the other
q + geom_signif(y_position = y.values.1,
xmin = x.min.values.1,
xmax = x.max.values.1,
annotations = labels.1,
tip_length = rep(0.02, length(labels.1)),
vjust = 0.5 ) +
geom_signif(y_position = y.values.2,
xmin = x.min.values.2,
xmax = x.max.values.2,
annotations = labels.2,
tip_length = rep(0.04, length(labels.2)),
vjust = 0.5 ) +
geom_signif(y_position = y.values.3,
xmin = x.min.values.3,
xmax = x.max.values.3,
annotations = labels.3,
tip_length = rep(0.04, length(labels.3)),
vjust = 0.5 ) +
geom_signif(y_position = y.values.4,
xmin = x.min.values.4,
xmax = x.max.values.4,
annotations = labels.4,
tip_length = rep(0.06, length(labels.4)),
vjust = 0.5 )
The output looks like this:
Barplot_with_significance_bars_within_and_between_groups
Related
I'm doing an analysis on air pollutants using Bayesian Kernel Machine Regression, using the bkmr package in R.
https://jenfb.github.io/bkmr/overview.html
The link is to Jennifer Bobb's instructions on how to use this package. I don't think it is relevant to the issue though. What I want to do is have PM2.5, O3, and NO2 show up in my charts with the 2.5, 3, and 2 as subscripts. I'm trying to use this function and getting no luck:
colnames(dat) <- c("LTE4", "$O[3]", "$PM[2.5]", "$NO[2]", "Diethyl", "Dimethyl", "age", "tmpf", "relh", "sex", "agany", "agself", "asthma")
When I do this what happens I just see these labels show up in the plots with with the $ and [] instead of subscripted numbers. Any ideas?
This is the full code I am using:
### January BKMR Analysis ###
## Hierarchical Variable Selection ##
## Updated June 6, 2022 ##
# Reading in necessary packages
library(tidyverse)
library(bkmr)
trio_semipro <- readRDS("C:/Users/Matt/OneDrive/Documents/Fresno Thesis/Thesis Code/trio_semipro.rds")
trio_semipro
dim(trio_semipro)
head(trio_semipro)
trio_semipro$log_lte4 <- log(trio_semipro$Final)
# Separating out dataframes for winter and summer to run separate models for each season
trio_semipro_w <- trio_semipro %>%
filter(visit_month == 1)
trio_semipro_s <- trio_semipro %>%
filter(visit_month == 2)
# Summer and Winter Dataframes
trio_semipro_w
trio_semipro_s
head(trio_semipro_w)
#view(trio_semipro_w)
dat = cbind(trio_semipro_w$log_lte4, trio_semipro_w$O3,
trio_semipro_w$PM25, trio_semipro_w$NO2, trio_semipro_w$diethyl, trio_semipro_w$dimethyl,
trio_semipro_w$age, trio_semipro_w$tmpf, trio_semipro_w$relh, trio_semipro_w$sex, trio_semipro_w$agriculture_anyone,
trio_semipro_w$agriculture_self, trio_semipro_w$asthma)
head(dat)
colnames(dat) = c("LTE4", "$O[3]", "$PM[2.5]", "$NO[2]", "Diethyl", "Dimethyl", "age", "tmpf", "relh", "sex", "agany", "agself", "asthma")
dat = as.data.frame(dat)
dat$sex
# recode the binary variable to be 0, 1 and NA
dat$agself = dat$agself-1
dat$agself[which(dat$agself==2)]=NA
dat$agself
# recode sex variable
dat$sex = dat$sex -1
# recode agany variable
dat$agany = dat$agany - 1
dat$agany[which(dat$agany==2)]=NA
#recode asthma variable
dat$asthma = dat$asthma - 1
dat$asthma[which(dat$asthma==2)]=NA
dat$asthma
dat$sex
dat$agany
# good
head(dat)
complete_dat = dat[-which(apply(dat, 1, anyNA)),]
dim(complete_dat)
# Fit BKMR
zscaled <- apply(complete_dat[,(2:6)], 2, scale)
yscaled <- scale(complete_dat$lte4)
xscaled <- cbind(scale(complete_dat[,7:9]), complete_dat[,10:13])
fit_bkmr = kmbayes(y=yscaled, Z= zscaled, X = xscaled,
iter = 20000, varsel = TRUE, groups=c(1,1,1,2,2), verbose=FALSE)
plot(fit_bkmr$sigsq.eps, type = "l")
TracePlot(fit = fit_bkmr, par = "beta", comp = 4)
TracePlot(fit = fit_bkmr, par = "sigsq.eps")
TracePlot(fit = fit_bkmr, par = "r", comp = 1)
# Estimating posterior inclusion probabilities
ExtractPIPs(fit_bkmr)
# Estimating h
y <- yscaled
Z <- zscaled
X <- xscaled
med_vals <- apply(Z, 2, median)
Znew <- matrix(med_vals, nrow = 1)
# Summarize model output
pred.resp.univar <- PredictorResponseUnivar(fit = fit_bkmr)
library(ggplot2) # Using ggplot to plot cross sections of h
ggplot(pred.resp.univar, aes(z, est, ymin = est - 1.96*se, ymax = est + 1.96*se)) +
geom_smooth(stat = "identity") +
geom_hline(yintercept = 0, lty = 5, col = "red2", alpha = 0.4) +
facet_wrap(~ variable, nrow = 1) +
ylab("h(z)")
# visualze the bivarate exposure-response function for two predictors, where
# all of the other predictors are fixed at a particular percentile.
pred.resp.bivar <- PredictorResponseBivar(fit = fit_bkmr, min.plot.dist = 1)
ggplot(pred.resp.bivar, aes(z1, z2, fill = est)) +
geom_raster() +
facet_grid(variable2 ~ variable1) +
scale_fill_gradientn(colours=c("#0000FFFF","#FFFFFFFF","#FF0000FF")) +
xlab("expos1") +
ylab("expos2") +
ggtitle("h(expos1, expos2)")
I generated a plot using a long format table, ggplot() and facet_wrap() functions in Rstudio. I want to add values of Tukey's tests applied to different levels of data and annotated with a system of stars (or letters) for significance.
Here is the example code :
# create a df for example
a <- paste0("Sample_", rep(1:100, 1))
b <- c(rep("Dubai", 30), rep("London", 35), rep("Bucarest", 35))
c <- c(rep("Sun", 16), rep("Rain", 16), rep("Cloud", 17), rep("Thunder", 16), rep("Star", 35))
d <- runif(n = 100, min = 0.5, max = 50)
e <- runif(n = 100, min = 0.5, max = 50)
f <- runif(n = 100, min = 0.1, max = 3)
df <- data.frame("Sample"= a, "Location"=b, "Obs"=c, "Measure1"=d, "Measure2"=e, "Measure3"=f)
# convert df to long format
long <- reshape2::melt(df, id.vars = c("Sample", "Location", "Obs"), measure.vars = c("Measure1", "Measure2", "Measure3"))
# make a plot
p <- ggplot(long,aes(Location,value, color=Obs)) +
facet_wrap(~ variable, drop=T, scale="free")+
geom_boxplot(outlier.colour = NA, alpha=0.8, position = position_dodge2(width=1, preserve="single"))+
geom_point(size=1.2, aes(shape=Obs), position=position_dodge(width=0.7, preserve='total'))+
scale_shape_manual("Obs", values = c(16,17,17,16,16),
labels = c("Sun",
"Rain",
"Cloud",
"Thunder",
"Star"))+
scale_color_manual("Obs",
values=c("#00BF7D", "#5B6BF7", "#00B0F6", "#A3A500", "#F8766D"),
labels = c("Sun",
"Rain",
"Cloud",
"Thunder",
"Star"))+
labs(x="Location", y = "Measure")+
theme(legend.text.align = 0)
p
I get this :
And I would like this :
I tried with geom_signif() and stat_compare_means() functions but without success.
Any idea please ?
Thank you for your attention.
This a reproducible example of my data
dat<-data.frame(
prec<-rnorm(650,mean=300),
temp<-rnorm(650,mean = 22),
pet<-rnorm(650,mean = 79),
bal<-rnorm(650,mean = 225))
colnames(dat)<-c("prec","temp","pet","bal")
dat<-ts(dat,start = c(1965,1),frequency = 12)
#splines
fit1<-smooth.spline(time(dat),dat[,1],df=25)
fit2<-smooth.spline(time(dat),dat[,2],df=25)
fit3<-smooth.spline(time(dat),dat[,3],df=25)
fit4<-smooth.spline(time(dat),dat[,4],df=25)
dat2 <- cbind(dat, fitted(fit1), fitted(fit2), fitted(fit3), fitted(fit4))
plot.zoo(window(dat2, start = 1965), xlab = "", screen = 1:4,
col = c(1:4, 1, 2, 3, 4),yax.flip = TRUE, bty="n")
How can I modify the color and the scale of the y axes in each plot to match the same color of the time series?
Create dat2 which contains both the series and the smooth splines, use window to start it at 1965, specify in screen= that the the columns be in panels 1:4 (it will recycle for the last 4 columns) and specify that the last 4 columns be black, i.e. 1, or modify colors to suit.
dat2 <- cbind(dat, fitted(fit1), fitted(fit2), fitted(fit3), fitted(fit4))
plot.zoo(window(dat2, start = 1965), xlab = "", screen = 1:4,
col = c(1:4, 1, 1, 1, 1))
Regarding the comment, to me it seems easier to read if the ticks, labels and axes are black but if you want to do that anyways use the mfrow= graphical parameter with a for loop and specify col.axis and col.lab in the plot.zoo call:
nc <- ncol(dat)
cols <- 1:nc # specify desired colors
opar <- par(mfrow = c(nc, 1), oma = c(6, 0, 5, 0), mar = c(0, 5.1, 0, 2.1))
for(i in 1:nc) {
dat1965 <- window(dat[, i], start = 1965)
plot(as.zoo(dat1965), col = cols[i], ylab = colnames(dat)[i], col.axis = cols[i],
col.lab = cols[i])
fit <- smooth.spline(time(dat1965), dat1965, df = 25)
lines(cbind(dat1965, fitted(fit))[, 2]) # coerce fitted() to ts
}
par(opar)
mtext("4 plots", line = -2, font = 2, outer = TRUE)
I'm using the function gammamixEM from the package mixtools. How can I return the graphical output of density as in the function normalmixEM (i.e., the second plot in plot(...,which=2)) ?
Update:
Here is a reproducible example for the function gammamixEM:
x <- c(rgamma(200, shape = 0.2, scale = 14), rgamma(200,
shape = 32, scale = 10), rgamma(200, shape = 5, scale = 6))
out <- gammamixEM(x, lambda = c(1, 1, 1)/3, verb = TRUE)
Here is a reproducible example for the function normalmixEM:
data(faithful)
attach(faithful)
out <- normalmixEM(waiting, arbvar = FALSE, epsilon = 1e-03)
plot(out, which=2)
I would like to obtain this graphical output of density from the function gammamixEM.
Here you go.
out <- normalmixEM(waiting, arbvar = FALSE, epsilon = 1e-03)
x <- out
whichplots <- 2
density = 2 %in% whichplots
loglik = 1 %in% whichplots
def.par <- par(ask=(loglik + density > 1), "mar") # only ask and mar are changed
mix.object <- x
k <- ncol(mix.object$posterior)
x <- sort(mix.object$x)
a <- hist(x, plot = FALSE)
maxy <- max(max(a$density), .3989*mix.object$lambda/mix.object$sigma)
I just had to dig into the source code of plot.mixEM
So, now to do this with gammamixEM:
x <- c(rgamma(200, shape = 0.2, scale = 14), rgamma(200,
shape = 32, scale = 10), rgamma(200, shape = 5, scale = 6))
gammamixEM.out <- gammamixEM(x, lambda = c(1, 1, 1)/3, verb = TRUE)
mix.object <- gammamixEM.out
k <- ncol(mix.object$posterior)
x <- sort(mix.object$x)
a <- hist(x, plot = FALSE)
maxy <- max(max(a$density), .3989*mix.object$lambda/mix.object$sigma)
main2 <- "Density Curves"
xlab2 <- "Data"
col2 <- 2:(k+1)
hist(x, prob = TRUE, main = main2, xlab = xlab2,
ylim = c(0,maxy))
for (i in 1:k) {
lines(x, mix.object$lambda[i] *
dnorm(x,
sd = sd(x)))
}
I believe it should be pretty straight forward to continue this example a bit, if you want to add the labels, smooth lines, etc. Here's the source of the plot.mixEM function.
I'm wondering if there is an easy way to plot the changes in position of elements between 2 lists in the form of a directed bipartite graph in R. For example, list 1 and 2 are vectors of character strings, not necessarily containing the same elements:
list.1 <- c("a","b","c","d","e","f","g")
list.2 <- c("b","x","e","c","z","d","a")
I would like to generate something similar to:
I've had a slight bash at using the igraph package, but couldn't easily construct what I would like, which I imagine and hope shouldn't be too hard.
Cheers.
Here is a simple function to do what you want. Essentially it uses match to match elements from one vector to another and arrows to draw arrows.
plotRanks <- function(a, b, labels.offset=0.1, arrow.len=0.1)
{
old.par <- par(mar=c(1,1,1,1))
# Find the length of the vectors
len.1 <- length(a)
len.2 <- length(b)
# Plot two columns of equidistant points
plot(rep(1, len.1), 1:len.1, pch=20, cex=0.8,
xlim=c(0, 3), ylim=c(0, max(len.1, len.2)),
axes=F, xlab="", ylab="") # Remove axes and labels
points(rep(2, len.2), 1:len.2, pch=20, cex=0.8)
# Put labels next to each observation
text(rep(1-labels.offset, len.1), 1:len.1, a)
text(rep(2+labels.offset, len.2), 1:len.2, b)
# Now we need to map where the elements of a are in b
# We use the match function for this job
a.to.b <- match(a, b)
# Now we can draw arrows from the first column to the second
arrows(rep(1.02, len.1), 1:len.1, rep(1.98, len.2), a.to.b,
length=arrow.len, angle=20)
par(old.par)
}
A few example plots
par(mfrow=c(2,2))
plotRanks(c("a","b","c","d","e","f","g"),
c("b","x","e","c","z","d","a"))
plotRanks(sample(LETTERS, 20), sample(LETTERS, 5))
plotRanks(c("a","b","c","d","e","f","g"), 1:10) # No matches
plotRanks(c("a", "b", "c", 1:5), c("a", "b", "c", 1:5)) # All matches
par(mfrow=c(1,1))
Here's a solution using igraph functions.
rankchange <- function(list.1, list.2){
grp = c(rep(0,length(list.1)),rep(1,length(list.2)))
m = match(list.1, list.2)
m = m + length(list.1)
pairs = cbind(1:length(list.1), m)
pairs = pairs[!is.na(pairs[,1]),]
pairs = pairs[!is.na(pairs[,2]),]
g = graph.bipartite(grp, as.vector(t(pairs)), directed=TRUE)
V(g)$color = c("red","green")[grp+1]
V(g)$label = c(list.1, list.2)
V(g)$x = grp
V(g)$y = c(length(list.1):1, length(list.2):1)
g
}
This builds and then plots the graph from your vectors:
g = rankchange(list.1, list.2)
plot(g)
Adjust the colour scheme and symbolism to suit using options detailed in the igraph docs.
Note this is not thoroughly tested (only tried on your sample data) but you can see how it builds a bipartite graph from the code.
With ggplot2:
v1 <- c("a","b","c","d","e","f","g")
v2 <- c("b","x","e","c","z","d","a")
o <- 0.05
DF <- data.frame(x = c(rep(1, length(v1)), rep(2, length(v2))),
x1 = c(rep(1 + o, length(v1)), rep(2 - o, length(v2))),
y = c(rev(seq_along(v1)), rev(seq_along(v2))),
g = c(v1, v2))
library(ggplot2)
library(grid)
ggplot(DF, aes(x=x, y=y, group=g, label=g)) +
geom_path(aes(x=x1), arrow = arrow(length = unit(0.02,"npc")),
size=1, color="green") +
geom_text(size=10) +
theme_minimal() +
theme(axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank())
This can of course be wrapped in a function easily.
Here's a generalization of nico's result for use with data frames:
plotRanks <- function(df, rank_col, time_col, data_col, color_col = NA, labels_offset=0.1, arrow_len=0.1, ...){
time_vec <- df[ ,time_col]
unique_dates <- unique(time_vec)
unique_dates <- unique_dates[order(unique_dates)]
rank_ls <- lapply(unique_dates, function(d){
temp_df <- df[time_vec == d, ]
temp_df <- temp_df[order(temp_df[ ,data_col], temp_df[ ,rank_col]), ]
temp_d <- temp_df[ ,data_col]
temp_rank <- temp_df[ ,rank_col]
if(is.na(color_col)){
temp_color = rep("blue", length(temp_d))
}else{
temp_color = temp_df[ ,color_col]
}
temp_rank <- temp_df[ ,rank_col]
temp_ls <- list(temp_rank, temp_d, temp_color)
names(temp_ls) <- c("ranking", "data", "color")
temp_ls
})
first_rank <- rank_ls[[1]]$ranking
first_data <- rank_ls[[1]]$data
first_length <- length(first_rank)
y_max <- max(sapply(rank_ls, function(l) length(l$ranking)))
plot(rep(1, first_length), 1:first_length, pch=20, cex=0.8,
xlim=c(0, length(rank_ls) + 1), ylim = c(1, y_max), xaxt = "n", xlab = NA, ylab="Ranking", ...)
text_paste <- paste(first_rank, "\n", "(", first_data, ")", sep = "")
text(rep(1 - labels_offset, first_length), 1:first_length, text_paste)
axis(1, at = 1:(length(rank_ls)), labels = unique_dates)
for(i in 2:length(rank_ls)){
j = i - 1
ith_rank <- rank_ls[[i]]$ranking
ith_data <- rank_ls[[i]]$data
jth_color <- rank_ls[[j]]$color
jth_rank <- rank_ls[[j]]$ranking
ith_length <- length(ith_rank)
jth_length <- length(jth_rank)
points(rep(i, ith_length), 1:ith_length, pch = 20, cex = 0.8)
i_to_j <- match(jth_rank, ith_rank)
arrows(rep(i - 0.98, jth_length), 1:jth_length, rep(i - 0.02, ith_length), i_to_j
, length = 0.1, angle = 10, col = jth_color)
offset_choice <- ifelse(length(rank_ls) == 2, i + labels_offset, i - labels_offset)
text_paste <- paste(ith_rank, "\n", "(", ith_data, ")", sep = "")
text(rep(offset_choice, ith_length), 1:ith_length, text_paste)
}
}
Here's an example using a haphazard reshape of the presidents dataset:
data(presidents)
years <- rep(1945:1974, 4)
n <- length(presidents)
q1 <- presidents[seq(1, n, 4)]
q2 <- presidents[seq(2, n, 4)]
q3 <- presidents[seq(3, n, 4)]
q4 <- presidents[seq(4, n, 4)]
quarters <- c(q1, q2, q3, q4)
q_label <- c(rep("Q1", n / 4), rep("Q2", n / 4), rep("Q3", n / 4), rep("Q4", n / 4))
q_colors <- c(Q1 = "blue", Q2 = "red", Q3 = "green", Q4 = "orange")
q_colors <- q_colors[match(q_label, names(q_colors))]
new_prez <- data.frame(years, quarters, q_label, q_colors)
new_prez <- na.omit(new_prez)
png("C:/users/fasdfsdhkeos/desktop/prez.png", width = 15, height = 10, units = "in", res = 300)
plotRanks(new_prez[new_prez$years %in% 1960:1970, ], "q_label", "years", "quarters", "q_colors")
dev.off()
This produces a time series ranking plot, and it introduces color if tracking a certain observation is desired: