Mixed plot with histogram and superimposed line plot in same figure - r

I know there are strong opinions about mixing plot types in the same figures, especially if there are two y axes involved. However, this is a situation in which I have no alternative - I need to create a figure using R that follows a standard format - a histogram on one axis (case counts), and a superimposed line graph showing an unrelated rate on an independent axis.
The best I have been able to do is stacked ggplot2 facets, but this is not as easy to interpret for the purposes of this analysis as the combined figure. The people reviewing this output will need it in the format they are used to.
I'm attaching an example below.
Any ideas?
For etiquette purposes, sample data below:
y1<-sample(0:1000,20,rep=TRUE)
y2<-sample(0:100,20,rep=TRUE)
x<-1981:2000

I feel your pain - have had to recreate plots before. even did it in SAS once
if it's a once off, I'm be tempted to go old-school. something like this:
# Generate some data
someData <- data.frame(Year = 1987:2009,
mCases = rpois(23, 3),
pVac = sample(55:80, 23, T))
par(mar = c(5, 5, 5, 5))
with(someData, {
# Generate the barplot
BP <- barplot(mCases, ylim = c(0, 18), names = Year,
yaxt = "n", xlab = "", ylab = "Measles cases in Thousands")
axis(side = 2, at = 2*1:9, las = 1)
box()
# Add the % Vaccinated
par(new = T)
plot(BP, pVac, type = "l", ylim = c(0, 100), axes = F, ylab = "", xlab = "")
axis(side = 4, las = 1)
nudge <- ifelse(pVac > median(pVac), 2, -2)
text(BP, pVac + nudge, pVac)
mtext(side = 4, "% Vaccinated", line = 3)
par(new = F)
})

Try library(plotrix)
library(plotrix)
## Create sample data
y2<-sample(0:80,20,rep=TRUE)
x2<-sort(sample(1980:2010,20,rep=F))
y1<-sample(0:18,20,rep=TRUE)
x1<-sort(sample(1980:2010,20,rep=F))
x<-1980:2010
twoord.plot(x1,y1,x2,y2,
lylim=c(0,18),rylim=c(0,100),type=c("bar","l"),
ylab="Measles Cases in thousands",rylab="% Vaccinated",
lytickpos=seq(0,18,by=2),rytickpos=seq(0,100,by=10),ylab.at=9,rylab.at=50,
lcol=3,rcol=4)

Related

"col" argument in plot function not working when a factor value is used for x - axis

I am doing quarterly analysis, for which I want to plot a graph. To maintain continuity on x axis I have turned quarters into factors. But then when I am using plot function and trying to color it red, the col argument is not working.
An example:
quarterly_analysis <- data.frame(Quarter = as.factor(c(2020.1,2020.2,2020.3,2020.4,2021.1,2021.2,2021.3,2021.4)),
AvgDefault = as.numeric(c(0.24,0.27,0.17,0.35,0.32,0.42,0.38,0.40)))
plot(quarterly_analysis, col="red")
But I am getting the graph in black color as shown below:
Converting it to a factor is not ideal to plot unless you have multiple values for each factor - it tries to plot a box plot-style plot. For example, with 10 observations in the same factor, the col = "red" color shows up as the fill:
set.seed(123)
fact_example <- data.frame(factvar = as.factor(rep(LETTERS[1:3], 10)),
numvar = runif(30))
plot(fact_example$factvar, fact_example$numvar,
col = "red")
With only one observation for each factor, this is not ideal because it is just showing you the line that the box plot would make.
You could use border = "red:
plot(quarterly_analysis$Quarter,
quarterly_analysis$AvgDefault, border="red")
Or if you want more flexibility, you can plot it numerically and do a little tweaking for more control (i.e., can change the pch, or make it a line graph):
# make numeric x values to plot
x_vals <- as.numeric(substr(quarterly_analysis$Quarter,1,4)) + rep(seq(0, 1, length.out = 4))
par(mfrow=c(1,3))
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
pch = 7, main = "Square Symbol", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
type = "l", main = "Line graph", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
plot(x_vals,
quarterly_analysis$AvgDefault, col="red",
type = "b", pch = 7, main = "Both", axes = FALSE)
axis(1, at = x_vals,
labels = quarterly_analysis$Quarter)
axis(2)
Data
set.seed(123)
quarterly_analysis <- data.frame(Quarter = as.factor(paste0(2019:2022,
rep(c(".1", ".2", ".3", ".4"),
each = 4))),
AvgDefault = runif(16))
quarterly_analysis <- quarterly_analysis[order(quarterly_analysis$Quarter),]

Plot with a normal and a reversed y axis

I have data sets containing daily precipitation and discharge data. Now I would like to plot everything in one plot. All data sets are of length 61, so they can share the same x axis. The discharge data should be plotted the "normal" way, meaning that the y axis starts at the bottom and is placed on the left side. The precipitation data should be plotted "from the top", meaning that the y axis is reversed and placed on the right side.
Here is some code for a minimal reproducible example:
precipitation <- runif(61, min=0, max=25)
discharge <- runif(61, min=370, max=2610)
The result should approximately look like this:
Anybody with an idea how to achieve this?
EDIT: thanks pascal for the answer that implies the usage of ggplot2.
I also found a way by myself to do it with Base R, in case it could help anybody in the future:
precipitation <- runif(61, min=0, max=25)
discharge <- runif(61, min=370, max=2610)
# plot with Base R
par(mar = c(5, 5, 3, 5), xpd = TRUE)
plot(precipitation, type= "l", ylim= c(0,80), ylab= "Precipitation [mm/day]", main= "Comparison",
xlab= "Day", col= "blue")
par(new = TRUE)
plot(discharge, type= "l", xaxt = "n", ylim= rev(c(0,5000)), yaxt = "n", ylab = "", xlab = "", col= "red", lty= 2)
axis(side = 4)
mtext("Discharge [m³/s]", side = 4, line = 3)
The ggplot2 way looks a bit fancier of course.
ggplot2 can be used to make plots with a second, inverted axis. One has to specify sec.axis in scale_y_continuous(). I'm using a transformation ((100-x)*100) for your data and apply it to the axis as well, so that it fits. This can be changed to any numbers.
ggplot() +
geom_line(aes(y=precipitation, x=1:61), col="orange") +
geom_line(aes(y=100-discharge/100, x=1:61), col="blue") +
scale_y_continuous(name="rain", sec.axis=sec_axis(~(100-.)*100, name= "discharge"))

formatting the x-axis exponential plot in R as a^x?

I have generated this plot in R with some strange numbers format in the x-axis:
enter image description here
I want to have in the x-axis the numbers in the format (ax) as 2^6, 6^6, 10^6. this would simplify the x-axis to get data in all points. Please do you have any suggestions?
Here my code :
data=read.csv("my_file.csv",row.names = 1)
plot(genes~Prot,cex=1.5,data, function(x) 10^x, xlab="Proteome
size(codons)",ylim=c(0,30), ylab="Genes in pathway")
abline(lm(prot~genes,data),lty=2, lwd=3,col="black")
Use xaxt = 'n' as an argument to plot to turn off the x-axis labelling. Then use the Axis function to set tick marks and label as required.
# Generating some data
power <- seq(1, 6, length.out = 20)
Prot = 10^power
genes <- runif(20, min = 5, max = 30)
# plotting
plot(x= Prot, y= genes, cex=1.5, xlab="Proteome size(codons)", ylab="Genes in pathway", xaxt = 'n', log = 'xy')
Axis(at = c(2^6, 6^6, 10^6), side = 1, labels = c('2^6', '6^6', '10^6'), las = 1)

VGAM percentile curve plot in R

I am running following code from help files of VGAM:
library(VGAM)
fit4 <- vgam(BMI ~ s(age, df = c(4, 2)), lms.bcn(zero = 1), data = bmi.nz, trace = TRUE)
qtplot(fit4, percentiles = c(5,50,90,99), main = "Quantiles", las = 1, xlim = c(15, 90), ylab = "BMI", lwd = 2, lcol = 4)
How can I just prevent putting points on the plot so that the graph shows only percentile curves? Is there some option in qtplot where I can suppress points on this graph, so that I do not need to resort to long ggplot route as done on this page: Percentiles from VGAM ? In my earlier question there were other issues also so this point got ignored. Thanks for your help.
There is no qtplot help page so I went to the package help Index and saw qtplot.lmscreg listed. It had a 'pcol.arg' to control points color so I set it to "transparent":
qtplot(fit4, percentiles = c(5,50,90,99), main = "Quantiles", las = 1,
xlim = c(15, 90), ylab = "BMI", lwd = 2, lcol = 4,
pcol.arg="transparent")

How to plot a broken line in R?

So I have the following MWE, a horizontal line expresses the mean of a particular day and the points are measurements of emotion.
I'd like to draw a line instead of points within a day between the points, but the line must have breaks between days. I can't seem to figure out how to do this.
I tried the example on this page, but that does not seem to work for my data.
A friend of mine managed to do this for the horizontal lines (they have spaces between days), but I can't seem to change my code to let it work for my measurements within days.
MWE:
beeps.MWE <- c(91.188697, 87.846194, 93.166418, 96.249094, 95.495146, 99.362597, 94.373646,
81.995712, 87.626009, 91.880172, 93.112647, 99.349234, 87.073372, 85.161982, 88.119728,
89.738318, 68.891181, 62.504569, 75.131526, 56.035989, 66.035109, 56.012537)
day.MWE <- rep(c(91.35869, 63.17620), each = 11)
loc.MWE <- c(8, 15)
plot(day.MWE, type = "n", pch = 15, cex = 1.5, ylim = c(40, 110), bty = "n",
ylab = "score on PA/NA", xlab = "days of person i", axes = FALSE)
dayUn <- unique(day.MWE)
for (i in seq_along(dayUn))
{
points(which(day.MWE==dayUn[i]),day.MWE[day.MWE==dayUn[i]], type = 'l', lwd = "2")
}
points(1:length(beeps.MWE), beeps.MWE, type = "p")
lines(1:length(beeps.MWE), rep(mean(day.MWE), 22), lwd = "2", lty = 2)
axis(1, at = c(1, 20), labels = c("day 1", "day 2"))
axis(2, las = 1)
This is the output of the above code:
You're nearly there with the code provided. Just add a line to the loop to draw the lines between the points:
for (i in seq_along(dayUn)){
# draw horizontal lines to show the mean per day
points(which(day.MWE==dayUn[i]),day.MWE[day.MWE==dayUn[i]], type = 'l', lwd = "2")
# draw a line that connects points within a day
points(which(day.MWE==dayUn[i]),beeps.MWE[day.MWE==dayUn[i]], lwd = "2", type='l')
}
Also note that points(x,y,type='l') is the same as lines(x,y). Makes more sense ;)

Resources