When I draw grid lines on a plot using abline() the grid lines are drawn over the data.
Is there a way to draw the abline() lines behind the data? I feel this would look better.
Example:
x <- seq(0, 10)
y <- x
plot(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
abline(h = seq(0, 10, .5), col = 'lightgray', lty = 3)
abline(v = seq(0, 10, .5), col = 'lightgray', lty = 3)
The plot produced has the gray grid lines going over the data (red line). I would like the red line to be on top of the gray lines.
The panel.first argument of plot() can take a list or vector of functions so you can put your abline() calls in there.
plot(1:4, panel.first =
c(abline(h = 1:4, lty = 2, col = 'grey')
,abline(v = 1:4, lty = 2, col = 'grey')))
Use plot() to set up the plotting window, but use type = "n" to not plot any data. Then do your abline() calls, or use grid(), and then plot the data using whatever low-level function is appropriate (here points() is fine).
x <- seq(0, 10)
y <- x
plot(x, y, type = "n")
abline(h = seq(0, 10, .5), col = 'lightgray', lty = 3)
abline(v = seq(0, 10, .5), col = 'lightgray', lty = 3)
points(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
or
## using `grid()`
plot(x, y, type = "n")
grid()
points(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
See ?grid for details of how to specify the grid as per your abline() version.
Plot first with type="n" to establish coordinates. Then put in the grid lines, then plot again with your regular plot type:
plot(x, y, col = 'red', type = 'n', lwd = 3, pch = 15)
abline(h = seq(0, 10, .5), col = 'lightgray', lty = 3)
abline(v = seq(0, 10, .5), col = 'lightgray', lty = 3)
par(new=TRUE)
plot(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
I admit that I have always thought the name for that par parameter was "backwards."
Another way of creating grid lines is to set tck=1 when plotting or in the axis function (you may still want to plot the points using points after creating the grid lines.
Related
I want to overlay three curves of the normal distribution with three different sigma values. I have done this:
curve(dnorm(x, mean(x), sd(x)), col = 2, lwd = 2)
par(new = TRUE)
curve(dnorm(x, mean(x), sd(x)/2), col = 3, lwd = 2)
par(new = TRUE)
curve(dnorm(x, mean(x), sd(x)*2), col = 4, lwd = 2)
And the result is
But I want to use only one y axis scale, so the three plots are one under the other and not on the same y scale. Also I want to expand the range of the x axis, to be from -3 to 3 for example
Open a blank graphics device first by setting plot parameter type = "n". Then add = TRUE the 3 curves.
plot(c(0, 1), c(0, 3), type = "n", xlab = "", ylab = "")
curve(dnorm(x, mean(x), sd(x)), col = 2, lwd = 2, add = TRUE)
curve(dnorm(x, mean(x), sd(x)/2), col = 3, lwd = 2, add = TRUE)
curve(dnorm(x, mean(x), sd(x)*2), col = 4, lwd = 2, add = TRUE)
You can use yaxt and xaxt to remove the y axis from the graph.
curve(dnorm(x, mean(x), sd(x)), col = 2, lwd = 2,ylab="My y axis name")
par(new = TRUE)
curve(dnorm(x, mean(x), sd(x)/2), col = 3, lwd = 2,yaxt='n',xaxt='n',ylab="")
par(new = TRUE)
curve(dnorm(x, mean(x), sd(x)*2), col = 4, lwd = 2,yaxt='n',xaxt='n',ylab="")
gives,
I am not an expert on stats, but I've been trying to plot a cdf out of an array of points. I've tried R and Python both. These are my example set of points:(1.5,1.5,2.5,3.5,3.5,3.5,4.5,5.5,5.5,6)
Using the ecdf function in R, I manage to get this:
This was my code:
data <- c(1.5,1.5,2.5,3.5,3.5,3.5,4.5,5.5,5.5,6)
plot(ecdf(data))
Is there a way to get the same plotted as a histogram or would that be fundamentally wrong?
Is this what you mean?
par(mar = c(5,5,2,5))
data <- c(1.5,1.5,2.5,3.5,3.5,3.5,4.5,5.5,5.5,6)
h <- hist(
data,
breaks = seq(0, 10, 1),
xlim = c(0,10))
par(new = T)
ec <- ecdf(data)
plot(x = h$mids, y=ec(h$mids)*max(h$counts), col = rgb(0,0,0,alpha=0), axes=F, xlab=NA, ylab=NA)
lines(x = h$mids, y=ec(h$mids)*max(h$counts), col ='red')
axis(4, at=seq(from = 0, to = max(h$counts), length.out = 11), labels=seq(0, 1, 0.1), col = 'red', col.axis = 'red')
mtext(side = 4, line = 3, 'Cumulative Density', col = 'red')
I have some barplot
barplot(1:3, axes=FALSE)
to which I would like to add horizontal gridlines with labels using base R.
I get the first part using
par(xpd = TRUE, mai=c(0.5,1,0.5,0.2)) # to extend lines to the left of plotting area
barplot(1:3, axes=FALSE) # plotting area
grid(nx=0, ny=3, col="gray") # horizontal grid lines
barplot(1:3, axes=FALSE, add=TRUE) # get grid lines into background
but I fail to get the labels on the left end. That is, at the left end of the gridlines, I would like to have the Y-values, here 1 and 2.
The documentation of ?grid gives a solution to this problem. From section Note.
Note
If more fine tuning is required, use abline(h = ., v = .) directly.
old_par <- par(xpd = TRUE, mai=c(0.5,1,0.5,0.2))
barplot(1:3, axes = FALSE)
abline(h = 1:3, col = "grey", lty = "dotted")
barplot(1:3, axes = FALSE, add = TRUE)
text(x = -0.5, y = 1:3, labels = 1:3)
par(old_par)
To have the y axis labels at the end of the grid lines and to place them automatically, a function can be defined.
segmText <- function(x0, x1, y, ...){
segments(x0 = x0, x1 = x1,
y0 = y, y1 = y, ...)
text(x = x0, y = y, labels = y)
}
old_par <- par(xpd = TRUE, mai = c(0.5,1,0.5,0.2)) # to extend lines to the left of plotting area
barplot(1:3, axes = FALSE)
segmText(x0 = -0.5, x1 = 4, y = 1:3, col = "grey", lty = "dotted")
barplot(1:3, axes = FALSE, add = TRUE)
par(old_par)
Edit
A simpler solution seems to be in the comment by user d.b
graphics.off()
barplot(1:3, axes = FALSE, col = NA, border = NA)
abline(h = 1:3, col = "grey", lty = "dotted")
barplot(1:3, axes = FALSE, add = TRUE)
axis(2, at = 1:3, labels = 1:3, las = 2, col = NA)
You could use lines() within a sapply() and use mtext(). Plot an empty plot beforehand.
plot(x=0:4, y=0:4, type="n", axes=FALSE, xlab="", ylab="")
sapply(1:3, function(x) lines(0:4, rep(x, 5), lty=3, col="gray"))
barplot(1:3, axes=FALSE, add=TRUE)
mtext(1:3, side=2, line=0, at=1:3, las=1, adj=0)
You can trim this by changing e.g. line=-1 or play around with adj.
Produces
a<-function(x) exp(-x)
b<-function(x) 0.75*exp(-0.75*x)
plot(a,xlim=c(-3,3),type="l",col="red3",lwd=2)
lines(b,xlim=c(-3,3),type="l",col="blue3")
I want to draw these two functions' graph in one axis, but an error shows:
Error in as.double(x) :
cannot coerce type 'closure' to vector of type 'double'
How to fix this?
a<-function(x) exp(-x)
b<-function(x) 0.75*exp(-0.75*x)
plot(a,xlim=c(-3,3),type="l",col="red3",lwd=2)
plot(b,xlim=c(-3,3),type="l",col="blue3", add = TRUE)
use plot() instead of lines() and add the add = TRUE parameter
EDIT: But I'd suggest using ggplot for graphics. This code:
library(ggplot2)
ggplot(data.frame(x=c(-3,3)), aes(x)) +
stat_function(fun=a, geom="line", aes(colour="Function a: exp(-x)")) +
stat_function(fun=b, geom="line", aes(colour="Function b: 0.75*exp(-0.75*x)")) +
labs(colour = "Functions")
will give you this nice image:
here is an approach utilizing the function curve which draws a curve corresponding to a function over the interval defined by from and to.
a <- function(x) exp(-x)
b <- function(x) 0.75*exp(-0.75*x)
plot(a, xlim = c(-3, 3), type = "l",col = "red3", lwd = 2)
curve(b, from = -3, to = 3, col = "blue3", add = T, lwd = 2)
legend("topright", c("a", "b"), col = c("red3", "blue3"), lty = 1, lwd = 2)
the call to plot is in fact a call to plot.function a S3 method for class function since the first argument is a function. If one types ?plot.function the documentation calls curve {graphics}.
equivalent approaches are:
curve(a, from = -3, to = 3, col = "red3", lwd = 2)
curve(b, from = -3, to = 3, col = "blue3", add = T, lwd = 2)
legend("topright", c("a", "b"), col = c("red3", "blue3"), lty = 1, lwd = 2)
and
plot(a, xlim = c(-3, 3), type = "l",col = "red3", lwd = 2)
plot(b, xlim = c(-3, 3), type = "l",col = "blue3", lwd = 2, add = T)
legend("topright", c("a", "b"), col = c("red3", "blue3"), lty = 1, lwd = 2)
since they all call curve.
I'm plotting a cdf of some data, and I've added logarithmic scale on the "x" axis.
The ticks spacing is exactly as I want it to be, but I'd like to be able to add
some tick marks on specific points.
I don't want to change the distribution of the ticks in my plot, from n by n to m by m, I want simply to have, among the ticks from n by n, some further tick marks on some values.
I'd like to have it reflected in both x and y axis, so that I can fit a grid into these new marks throughout the graph.
So far I have the graph, and the grid -- I don't mind about having the grid behind or upon the graph, I just want to add some custom ticks.
# Cumulative Distribuition
pdf("g1_3.pdf")
plot(x = f$V2, y = cumsum(f$V1), log = "x", pch = 3,
xlab = "Frequency", ylab = "P(X <= x)",
panel.first = grid(equilogs = FALSE))
axis(1, at = c(40, 150))
abline(h = 0.6, v = 40, col = "lightgray", lty = 3)
abline(h = 0.6, v = 150, col = "lightgray", lty = 3)
dev.off()
UPDATE: The graph I have so far:
Considering the initial script, and the tips given by #BenBolker, I had to use:
axis(side = 1, at = c([all the ticks you want]))
in order to add the ticks in the graph. Here's the final result:
# Cumulative Distribuition
pdf("g1_3.pdf")
plot(x = f$V2, y = cumsum(f$V1), log = "x", pch = 3,
xlab = "Frequency", ylab = "P(X <= x)", axes = FALSE)
ticks = c(1, 5, 10, 40, 150, 500, 1000)
axis(side = 1, at = ticks)
axis(side = 2)
abline(h = seq(0, 1, 0.2), v = ticks, col = "lightgray", lty = 3)
box()