Plot axis not meeting at origin - r

Consider the following vector:
q1 <- c(1000000.0, 908364.8, 876009.1, 847892.8, 824808.3, 805416.2, 785266.2, 770997.1, 753908.6, 744599.9, 706777.6, 674659.9, 634654.4, 601440.4, 568259.7, 535361.3, 493679.9, 465526.5, 429766.6, 395244.7, 361483.2, 332136.6, 308574.5, 285500.6, 262166.2 ,237989.0 , 210766.1, 188578.1, 166762.3 , 140399.8 ,114865.5)
Here is the plot:
dev.new(width=10, height=5)
par(xaxs='i',yaxs='i')
plot(q1, type = "l", lty = 1, lwd = 2, col = "green", xaxt = 'n', xlim = c(0,30), bty = "l")
x.ticks = seq(from = 0, to = 30, by = 5)
axis(1, at = x.ticks+1, labels=paste("Year", x.ticks, sep=" "))
For some reason, my x-axis and y-axis are not meeting at (0,0)! I tried fixing this by using par(xaxs='i',yaxs='i'), but it doesn't do the trick in this case?
Any ideas? Thanks!

If you do not specify ylim, R will fit the plot area to the data, not extend the plot to the origin. This will fix it:
plot(q1, type = "l", lty = 1, lwd = 2, col = "green", xaxt = 'n',
xlim = c(0,30), ylim = c(0, max(q1, na.rm = TRUE)), bty = "l")
I wrote the ylim to look for the maximum in q1. You can change it to a fixed value.
Here is the full code I ran to make it work:
q1 <- c(1000000.0, 908364.8, 876009.1, 847892.8, 824808.3, 805416.2,
785266.2, 770997.1, 753908.6, 744599.9, 706777.6, 674659.9,
634654.4, 601440.4, 568259.7, 535361.3, 493679.9, 465526.5,
429766.6, 395244.7, 361483.2, 332136.6, 308574.5, 285500.6,
262166.2 ,237989.0 , 210766.1, 188578.1, 166762.3 , 140399.8 ,114865.5)
dev.new(width=10, height=5)
par(xaxs='i',yaxs='i')
plot(q1, type = "l", lty = 1, lwd = 2, col = "green",
xaxt = 'n', xlim = c(1,30), ylim = c(0, max(q1)), bty = "l")
x.ticks = seq(from = 0, to = 30, by = 5)
axis(1, at = x.ticks + 1, labels=paste("Year", x.ticks, sep=" "))

Related

Plotting in the same graph and getting the same axis in R

I have been trying to plot my results in a graph. However, when watching the result I see that each have its own y-axis that does not correspond to the others. How could I possibly fix my problem?
RMSFE_AR <- c(0.380231, 0.3965452, 0.3408504, 0.398722)
RMSFE_RW <- c(0.492315, 0.4034821, 0.3671059, 0.3884792)
RMSFE_VAR <- c(0.429498, 0.4180072, 0.3546557, 0.4059629)
RMSFE_BVAR <- c(0.34, 0.3588872, 0.3510698, 0.3411622)
par(mfrow = c(1,1))
plot(RMSFE_AR, type = "l",
ylab = "", xlab = "", col = "red", lty = 2, xaxt="n", ylim=c(0.32,0.5))
axis(1, at = 1:4, labels = c("1", "3", "6", "12"))
par(new = TRUE)
plot(RMSFE_RW, type = "l",
ylab = "", xlab = "", col = "blue", lty = 2, axes=FALSE)
par(new = TRUE)
plot(RMSFE_VAR, type = "l",
ylab = "", xlab = "", col = "green", lty = 2, axes=FALSE)
par(new = TRUE)
plot(RMSFE_BVAR, type = "l",
ylab = "", xlab = "", col = "dark blue", lty = 2, axes=FALSE)
mtext("", side = 4, line = 3)
legend(par('usr')[1], par('usr')[3], bty='n', xpd=NA,cex = 0.7,
c("RMSFE AR(1)", "RMSFE RW", "RMSFE VAR", "RMSFE BVAR"),
col = c("red", "blue", "green", "dark blue"), lty = c(2, 2, 2, 2))
Create a data.frame, DF, from the data and col color vector and then use plot with type = "n" to set the appropriate ranges and then actually draw the lines using lines.
# inputs
DF <- data.frame("RMSFE AR(1)" = RMSFE_AR,
"RMSFE RW" = RMSFE_RW,
"RMSFE VAR" = RMSFE_VAR,
"RMSFE BVAR" = RMSFE_BVAR,
row.names = c(1, 3, 6, 12),
check.names = FALSE)
col <- c("red", "blue", "green", "dark blue")
x <- 1:nrow(DF)
plot(range(x), range(DF), type = "n", xlab = "", ylab = "", xaxt = "n")
axis(1, at = x, labels = rownames(DF))
for(i in 1:ncol(DF)) lines(DF[[i]], col = col[i], lty = 2)
legend("topright", legend = names(DF), bty = 'n', xpd = NA, cex = 0.7,
col = col, lty = 2)
or even easier using DF and col from above:
x <- 1:nrow(DF)
matplot(DF, lty = 2, type = "l", col = col, ylab = "", xaxt = "n")
axis(1, at = x, labels = rownames(DF))
legend("topright", legend = names(DF), bty = 'n', xpd = NA, cex = 0.7,
col = col, lty = 2)
You can use the following code:
plot(RMSFE_AR, type = "l",
ylab = "", xlab = "", col = "red", lty = 2, xaxt="n", ylim=c(0.32,0.5))
axis(1, at = 1:4, labels = c("1", "3", "6", "12"))
lines(RMSFE_RW, type = "l", col = "blue", lty = 2, axes=FALSE)
lines(RMSFE_VAR, type = "l", col = "green", lty = 2, axes=FALSE)
lines(RMSFE_BVAR, type = "l", col = "dark blue", lty = 2, axes=FALSE)
mtext("", side = 4, line = 3)
legend("topright", bty='n', xpd=NA,cex = 0.7,
c("RMSFE AR(1)", "RMSFE RW", "RMSFE VAR", "RMSFE BVAR"),
col = c("red", "blue", "green", "dark blue"), lty = c(2, 2, 2, 2))
Output:
Sorry, but it has to be done: You could use ggplot2.
library(ggplot2)
# reshape data so ggplot likes it
df <- data.frame(
var = rep(c("RMSFE_AR", "RMSFE_RW", "RMSFE_VAR", "RMSFE_BVAR"), each = 4),
x = rep(c(1,3,6,12), 4),
y = c(RMSFE_AR, RMSFE_RW, RMSFE_VAR, RMSFE_BVAR))
# make a plot
ggplot(df, aes(x = x, y = y, col = var)) +
geom_line(linetype = "longdash", size = 1) + # add line
scale_color_discrete(labels = c("RMSFE AR(1)", "RMSFE RW", "RMSFE VAR", "RMSFE BVAR")) + # rename legend items
labs(col = "", x = "", y = "") + # set legend and axis titles
theme_light() # prettier

How to remove the zero labels in Histogram plot in R?

Any tips to remove the zero labels in between the histogram bars?
hist(links$Survey_Duration, breaks = seq(0,50,5), main = "Survey Duration",
labels = TRUE, border = "black",
xlab = "Survey", ylim = c(0, 15), col = "gray", las = 1, xaxt='n')
axis(side=1, at=seq(0,50,5), labels=seq(0,50,5))
abline(v = mean(links$Survey_Duration), col = "royalblue", lwd = 1.5)
abline(v = median(links$Survey_Duration), col = "red", lwd = 1.5)
legend(x = "topright", c("Mean", "Median"), col = c("royalblue","red"),
lwd = c(1.5,1.5))
How about this?
# modify data so there's zero in one of the bins
mtcars$mpg <- ifelse(mtcars$mpg >= 25 & mtcars$mpg <= 30, NA, mtcars$mpg)
# save plot parameters
h <- hist(mtcars$mpg, plot = FALSE)
# produce plot
plot(h, ylim = c(0, 14))
# add labels manually, recoding zeros to nothing
text(h$mids, h$counts + 1, ifelse(h$counts == 0, "", h$counts))
A slightly different answer using the labeling in hist instead of adding text afterwards.
You do not provide your data, so I will use some data that is handy to illustrate.
The labels argument can specify the individual labels
H1 = hist(iris$Sepal.Length, breaks = 3:8, plot=FALSE)
BarLabels = H1$counts
BarLabels[BarLabels == 0] = ""
hist(iris$Sepal.Length, breaks = 3:8, labels = BarLabels)
Thanks #Daniel Anderson, it Ok now (Thumbs Up)
links$Survey_Duration <- ifelse(links$Survey_Duration > 15 &
links$Survey_Duration <= 25,
NA,
links$Survey_Duration)
h <- hist(links$Survey_Duration, breaks = seq(0,50,5), plot = FALSE)
plot(h, ylim = c(0, 14), main = "Survey Duration", xlab = "Time", col = "gray", las = 1)
text(h$mids, h$counts + 1, ifelse(h$counts == 0, "", h$counts))
axis(side=1, at=seq(0,50,5), labels=seq(0,50,5))
abline(v = mean(links$Survey_Duration), col = "royalblue", lwd = 1.5)
abline(v = median(links$Survey_Duration), col = "red", lwd = 1.5)
legend(x = "topright",
c("Mean", "Median"),
col = c("royalblue","red"),
lwd = c(1.5,1.5))

How can I plot vertical and horizontal lines even when xpd=TRUE?

Here is a simplified plot to work with:
env <- data.frame(site = c('BLK','DUC','WHP','BLK','DUC','WHP','BLK','DUC','WHP'),
sal = c(5,6,3,2,4,5,6,8,4),
date = c(2013,2013,2013,2015,2015,2015,2017,2017,2017))
sitelist <- c('BLK','DUC','WHP')
par(mar=c(3,5,3,6), xpd = T)
plot(sal~date, data = env, type = 'n', ylim = c(0,10), ylab = 'Salinity',
bty = 'n', xlab = '')
abline(v=2016, col = 'khaki', lwd = 20)
abline(mean(env$sal), 0, lty = 3)
for (ii in seq_along(sitelist)) {
i <- sitelist[ii]; lines(sal[site==i] ~ date[site==i], data = env,
col = c(4,2,5)[ii], lwd = 2,
lty = c(1,2,3)[ii]);
points(sal[site==i] ~ date[site==i], data = env,
pch = c(0,1,2)[ii], col = c(4,2,5)[ii])}
legend('topright', title = 'sites', inset=c(-0.2,0), lty = c(1,2,3),
col = c(4,2,5), lwd = 2, sitelist,
pch = c(0,1,2))
As written, this code yields a plot where the abline functions create lines that go outside of the boundaries of the plot, thanks to xpd=T. However, I don't want to set xpd=F, because I won't be able to plot my legend outside of the boundaries. The solution must either be a way to plot a legend outside of the boundaries with xpd=F or a way to plot lines that stop at the boundaries. Ideally, the solution would use the base program and be fairly standard, so I could drop it into each of my ~20 plots without too much customization.
I tried using segments but was not happy with the rounded edges of the segment, as my vertical line is supposed to be a sort of shaded area to indicate a certain time period.
You can either set xpd to FALSE in the par call and insert xpd = TRUE in the legend call like this:
env <- data.frame(site = c('BLK','DUC','WHP','BLK','DUC','WHP','BLK','DUC','WHP'),
sal = c(5,6,3,2,4,5,6,8,4),
date = c(2013,2013,2013,2015,2015,2015,2017,2017,2017))
sitelist <- c('BLK','DUC','WHP')
par(mar=c(3,5,3,6), xpd = F)
plot(sal~date, data = env, type = 'n', ylim = c(0,10), ylab = 'Salinity',
bty = 'n', xlab = '')
abline(v=2016, col = 'khaki', lwd = 20)
abline(mean(env$sal), 0, lty = 3)
for (ii in seq_along(sitelist)) {
i <- sitelist[ii]; lines(sal[site==i] ~ date[site==i], data = env,
col = c(4,2,5)[ii], lwd = 2,
lty = c(1,2,3)[ii]);
points(sal[site==i] ~ date[site==i], data = env,
pch = c(0,1,2)[ii], col = c(4,2,5)[ii])}
legend('topright', title = 'sites', inset=c(-0.2,0), lty = c(1,2,3),
col = c(4,2,5), lwd = 2, sitelist,
pch = c(0,1,2),
xpd = T)
Or keep xpd = TRUE in the par call and set xpd to FALSE in the abline calls like this:
env <- data.frame(site = c('BLK','DUC','WHP','BLK','DUC','WHP','BLK','DUC','WHP'),
sal = c(5,6,3,2,4,5,6,8,4),
date = c(2013,2013,2013,2015,2015,2015,2017,2017,2017))
sitelist <- c('BLK','DUC','WHP')
par(mar=c(3,5,3,6), xpd = T)
plot(sal~date, data = env, type = 'n', ylim = c(0,10), ylab = 'Salinity',
bty = 'n', xlab = '')
abline(v=2016, col = 'khaki', lwd = 20,xpd=F)
abline(mean(env$sal), 0, lty = 3,xpd=F)
for (ii in seq_along(sitelist)) {
i <- sitelist[ii]; lines(sal[site==i] ~ date[site==i], data = env,
col = c(4,2,5)[ii], lwd = 2,
lty = c(1,2,3)[ii]);
points(sal[site==i] ~ date[site==i], data = env,
pch = c(0,1,2)[ii], col = c(4,2,5)[ii])}
legend('topright', title = 'sites', inset=c(-0.2,0), lty = c(1,2,3),
col = c(4,2,5), lwd = 2, sitelist,
pch = c(0,1,2))
This should solve your issue.
Replace
abline(v=2016, col = 'khaki', lwd = 20)
abline(mean(env$sal), 0, lty = 3)
with
lines(c(2013, 2017), rep(mean(env$sal), 2), col="black", lwd = 2, lty = 2)
lines(rep(2016, 2), c(0, 10), col="khaki", lwd = 20)
Source: https://stackoverflow.com/a/24741885/5874001
par(mar=c(3,5,3,6), xpd = T)
plot(sal~date, data = env, type = 'n', ylim = c(0,10), ylab = 'Salinity', bty = 'n', xlab = '')
lines(c(2013, 2017), rep(mean(env$sal), 2), col="black", lwd = 2, lty = 2)
lines(rep(2016, 2), c(0, 10), col="khaki", lwd = 20)
for (ii in seq_along(sitelist)) {
i <- sitelist[ii]; lines(sal[site==i] ~ date[site==i],
data = env,
col = c(4,2,5)[ii],
lwd = 2,
lty = c(1,2,3)[ii]);
points(sal[site==i] ~ date[site==i], data = env,
pch = c(0,1,2)[ii], col = c(4,2,5)[ii])}
legend('topright', title = 'sites', inset=c(-0.2,0),
lty = c(1,2,3), col = c(4,2,5), lwd = 2,
sitelist, pch = c(0,1,2))
If you have 20+ plots, I'd look to see if you can write a loop to perform that task.

Misalignment when using "adj" in title() for an R plot

I want to have my titles be above my points in a pdf plot. It seems R thinks my title is wider than my plot area even though I have my right and left plot margins set to zero.
x <- seq(from = 0.1, to = 0.9, by = 0.1)
xtitle <- c("0.1","0.2","0.3","0.4","0.5","0.6","0.7","0.8","0.9")
pdf("testpdfopts.pdf", width = 16)
par(mar = c(0, 0, 1, 0)) # only need margin at top for title
plot(
x,
rep(0.9,length(x)),
xlim = c(0, 1),
ylim = c(0, 1),
cex = 1,
xaxt = "n",
yaxt = "n",
xlab = "",
ylab = ""
)
for (i in 1:length(x)) {
title(xtitle[i],adj=x[i],cex.main=1)
}
dev.off()
Thanks in advance for any assistance
I am sort of confused with what you are trying to do. Maybe I should put my comment into complete code:
x <- seq(from = 0.1, to = 0.9, by = 0.1)
plot(
x,
rep(0.9,length(x)),
xlim = c(0, 1),
ylim = c(0, 1),
cex = 1,
xaxt = "n",
yaxt = "n",
xlab = "",
ylab = ""
)
axis(3, at = 1:9/10)
Is this equivalent to what you aim to achieve?
You can get character labels too:
x <- seq(from = 0.1, to = 0.9, by = 0.1)
plot(
x,
rep(0.9,length(x)),
xlim = c(0, 1),
ylim = c(0, 1),
cex = 1,
xaxt = "n",
yaxt = "n",
xlab = "",
ylab = ""
)
axis(3, at = 1:9/10, labels = letters[1:9])

Changing the size of the text in the axis labels of an Ecdf plot

I've constructed an Ecdf plot from the Hmisc package with the following call:
require(Hmisc)
Ecdf(latency_targ1, group = CONDITION, lty = c(1, 2, 3, 4),
lwd = 4, label.curves = list(method = 'arrow',
keys = "lines", lwd = 2), xlim = c(0,500),
subtitles = FALSE, xlab = "Latency",
ylab = "Proportion latency <= x")
I have been unable to find how to change the size of the axis labels of the plot and the default size is rather small.
Try this:
Ecdf(latency_targ1, group = CONDITION, lty = c(1, 2, 3, 4),
lwd = 4, label.curves = list(method = 'arrow',
keys = "lines", lwd = 2), xlim = c(0,500),
subtitles = FALSE, xlab = "Latency",
ylab = "Proportion latency <= x",
cex.lab=1.5, xaxt="n", yaxt="n")
axis(2, cex.axis=1.5)
axis(1, cex.axis=1.5)

Resources