Is it possible to set background of a plot to be coloured in such a way:
col = c("grey", "white")
par(bg = rep(col, length.out = 5))
So that grey and white lines would repeat length.out number of times?
I'm not quite sure what you are after. If you want colour rectangles, then use rect
add_bg = function() rect(-3:2, -3, -2:3, 3, col=1:2)
plot(rnorm(10), rnorm(10), xlim=c(-3, 3), ylim=c(-3, 3),
bg=3,pch=21,cex=2, panel.first=add_bg())
to get a stripped effect. If you just want vertical lines, then use grid
no=10
## For horizontal lines set ny=no, nx=0
plot(rnorm(10), rnorm(10), xlim=c(-3, 3), ylim=c(-3, 3),
bg=3,pch=21,cex=2, panel.first=grid(ny=0,nx=no, col=1:2))
In both examples, I used the panel.first argument. When the graph is drawn the grid/rectangles are placed behind the points.
Related
When adding ticks to a plot (more ticks than default), how does one get the grid() to align the grid to the ticks?
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,10), ylim=c(0,10))
grid(lwd=2, nx=10, ny=10)
Tried changed the xlim and different numbers for the nx arg in grid (number of cells), but the grid simply doesn't line up.
Related, but doesn't answer question: Aligning grid lines in R, bReeze package
Related, and uses workaround: Align grid with ticks
Is the workaround the most efficient option?
You could use abline to draw grids. You can specify where the grids should be with h (for horizontal lines) and v (for vertical lines)
#Plot
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,10), ylim=c(0,10))
#Add horizontal grid
abline(h = c(0,2,4,6,8,10), lty = 2, col = "grey")
#Add vertical grid
abline(v = 1:10, lty = 2, col = "grey")
Another workaround is to use axis where tck value is 1. With axis, you can specify where the grids should be with at
#Plot
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,10), ylim=c(0,10))
#Add horizontal grid
axis(2, at = c(0,2,4,6,8,10), tck = 1, lty = 2, col = "grey", labels = NA)
#Add vertical grid
axis(1, at = 1:10, tck = 1, lty = 2, col = "grey", labels = NA)
#Add box around plot
box()
The problem is that grid is putting nx grid lines in the user space, but plot is adding 4% extra space on each side. You can take control of this. Adding xaxs="i", yaxs="i" to your plot will turn off the extra space. But then your upper right point will be cut off, so you need to change the xlim and ylim values and change nx to match. Final code is:
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,11), ylim=c(0,11),
xaxs="i", yaxs="i")
grid(lwd=2, nx=11, ny=11)
The answer to your question
When adding ticks to a plot (more ticks than default), how does one get the grid() to align the grid to the ticks?
is:
Using function axis to obtain the x axis tick locations created by plot function in combination with abline
Concretely, you substitute the line
grid(lwd=2, nx=10, ny=10)
by the following three lines
x_ticks <- axis(1, 0:10, labels = FALSE)
grid(lwd = 2, ny = NULL, nx = NA)
abline(v = x_ticks, lwd = 2, lty = 3, col = "lightgray")
and the result will be
You can control both x ticks and y ticks and get rid of the grid function. In this case the 3 lines would be
x_ticks <- axis(1, 0:10, labels = FALSE)
y_ticks <- axis(2, labels = FALSE)
abline(v = x_ticks, h = y_ticks, lwd = 2, lty = 3, col = "lightgray")
I would vote for the workaround. Because if you look at manual from ?grid, it has this statement,
"Note: If more fine tuning is required, use ‘abline(h = ., v = .)’
directly."
This question already has answers here:
How can I plot with 2 different y-axes?
(6 answers)
Closed 6 years ago.
i'm having troubles in a multi axis barplot. I have an X,Y axis with bars and dots in the same graph. The point is that I have to shown both of them in different scales
While I can shown both (bars and dots) correctly, the problem comes when I try to set different scales in left and right axis. I dont know how to change the aditional axis scale, and how to bind the red dots to the right axis, and the bars to the left one.
This is my code and what I get:
labels <- value
mp <- barplot(height = churn, main = title, ylab = "% churn", space = 0, ylim = c(0,5))
text(mp, par("usr")[3], labels = labels, srt = 45, adj = c(1.1,1.1), xpd = TRUE, cex=.9)
# Population dots
points(popul, col="red", bg="red", pch=21, cex=1.5)
# Churn Mean
media <- mean(churn)
abline(h=media, col = "black", lty=2)
# Population scale
axis(side = 4, col= "red")
ylim= c(0,50)
ylim= c(0,5)
What I want is to have left(grey) axis at ylim=c(0,5) with the bars bound to that axis. And the right(red) axis at ylim=c(0,50) with the dots bound to that axis...
The goal is to represent bars and points in the same graph with diferent axis.
Hope I explained myself succesfully.
Thanks for your assistance!
Here is a toy example. The only "trick" is to store the x locations of the bar centers and the limits of the x axis when creating the barplot, so that you can overlay a plot with the same x axis and add your points over the centers of the bars. The xaxs = "i" in the call to plot.window indicates to use the exact values given rather than expanding by a constant (the default behavior).
set.seed(1234)
dat1 <- sample(10, 5)
dat2 <- sample(50, 5)
par(mar = c(2, 4, 2, 4))
cntrs <- barplot(dat1)
xlim0 <- par()$usr[1:2]
par(new = TRUE)
plot.new()
plot.window(xlim = xlim0, ylim = c(0, 50), xaxs = "i")
points(dat2 ~ cntrs, col = "darkred")
axis(side = 4, col = "darkred")
At first I thought this would be trivial, but I could not figure out how to combine rectangles with lines in the legend of a lattice plot. Consider the following example:
library(latticeExtra)
xyplot(rnorm(10) ~ 1:10,
key=list(rectangles=list(size=2, border=F),
text=list(c("Zero", "One", "Two"), col="black"),
col=c("black", "lightgrey", "darkgrey"), divide=1, columns=1,
x=0.01, y=0.95, corner=c(0,1) ),
panel=function(x,...){
panel.abline(v=3, lty="dashed")
panel.xblocks(x,x>5, col="lightgrey")
panel.xblocks(x,x>7, col="darkgrey")
panel.xyplot(x, ...) } )
Instead of 3 rectangles, I would like to have 2 rectangles filled with the appropriate colours, and one dashed line above or below these two rectangles. If I provide a lines argument, then both lines and rectangles will be drawn for all elements (i.e. there will be 2 rectangles and 2 lines simultaneously next to each other).
How can I set up the legend key so that I get this mix of "symbols"? That is, how can I get one dashed line and two rectangles with the appropriate text and colours?
Any help is greatly appreciated! My apologies if this is trival. Please help me see the obvious! :)
This is a rather late answer but it is something I still do. One approach is to use auto.key in the function and then modify the lattice object with update(obj, key = newKey). A more general approach, as suggested by #josh-obrien, is to use the grid functions that under lattice. However, this typically requires empirical tweaking of the coordinates as can be seen in the need to use 3 decimal places of precision to place the dashed lines.
# relative position may be sensitive to absolute sizes
library(latticeExtra)
dev.new(width = 5, height = 5)
set.seed(1234)
# same code as in question, re-written a little bit
# using "transparent" for the 1st of the three rectangles
# using a grid call in the panel function to place the dashed line
xyplot(rnorm(10) ~ 1:10,
key = list(rectangles = list(size = 2, border = FALSE,
col = c("transparent", "lightgrey", "darkgrey")),
text = list(c("Zero", "One", "Two"), col = "black"),
columns = 1, corner = c(0.01, 0.95)),
panel = function(x,...) {
panel.abline(v = 3, lty = "dashed")
panel.xblocks(x, x > 5, col = "lightgrey")
panel.xblocks(x, x > 7, col = "darkgrey")
panel.xyplot(x, ...)
grid::grid.lines(c(0.04, 0.07), c(0.935, 0.935),
gp = gpar(lty = "dashed", col = "black"))
}
)
[![plot with combined elements in legend][1]][1]
[1]: https://i.stack.imgur.com/K7AJN.png
I am trying to make a plot in R that has a portion of the plot grey to emphasize this area. Unlike other examples, I don't want to color an area under a plot, but instead color an area on a plot starting at one area and going to the end of the graph. When I try to use rect() or polygon() it obscures the plots I want to emphasize.
For example:
x_mean <- c(1, 2, 3, 4)
y_mean <- c(1, 1, 1, 1)
y_max <- c(4, 4, 4, 4)
y_min <- c(-4, -4, -4, -4)
x_shade <- c(2, 3, 4)
y_max_shade <- c(4, 4, 4)
y_min_shade <- c(-4, -4, -4)
plot(x=rep(x_mean, 3), y=c(y_mean, y_max, y_min), bty='n', type="n" )
arrows(x0=x_mean, y0=y_min, x1=x_mean, y1=y_max, length=0)
points( x=x_mean, y=y_mean, pch=16)
This will plot 4 lines on the graph. How do I draw a grey box in the background from the 2nd line to the end of the plot?
Just so that you're left with more than just a comment, here's a possible solution:
plot(x=rep(x_mean, 3), y=c(y_mean, y_max, y_min), bty='n', type="n" )
rect(2,-4,4,4,col = rgb(0.5,0.5,0.5,1/4))
arrows(x0=x_mean, y0=y_min, x1=x_mean, y1=y_max, length=0)
points( x=x_mean, y=y_mean, pch=16)
Note that I also demonstrated how to use alpha blending in the color specification (using rgb). This can also be useful for this sort of thing. Try moving the rect line to the end, and notice that the results still look ok, because the fill color is partially transparent.
I've found this answer to be pretty great for shading background parts of R.
Some context:
panel.first = rect(c(1,7), -1e6, c(3,10), 1e6, col='green', border=NA)
The first two arguments c(1,7) are the starting values for the shaded rectangle, and following arguments c(3,10) are where the shading ends. This creates a shaded region from 1-3 and 7-10.
I am embarrassed to ask this simple question, but has been in kicking my mind for several days whenever I create a plot:
plot (x = 1:10, y = rnorm (10, 5, 2))
grid (10,10, lty = 6, col = "cornsilk2")
I want to position the grids right at where axis are labelled, i.e. at 2, 4, 6, 8, 10 in x axis and similarly 3, 4, 5, 6, 7, 8 in y axis.
I want to automate the process as whenever the plot size changes the default label behaviour changes. See the following plot:
From ?grid description of the nx and ny arguments:
When NULL, as per default, the grid aligns with the tick marks on the
corresponding default axis (i.e., tickmarks as computed by axTicks)
plot (x = 1:10, y = rnorm (10, 5, 2))
grid (NULL,NULL, lty = 6, col = "cornsilk2")
For reference, there is a way to control the grid and axes parameters directly from the plot() command, if we are not defining a custom tick interval:
plot(x = 1:10, y = rnorm(10, 5, 2), xlim=c(1, 10), ylim=c(1, 10), panel.first=grid())
The plot.default() documentation gives more information about these parameters.
When using a custom ticks interval, the easiest is to draw the grid using abline:
plot(x = 1:10, y = rnorm(10, 5, 2), xaxp=c(1, 10, 10), yaxp=c(1, 10, 10), axes=FALSE)
axis(1, 1:10)
axis(2, 1:10)
abline(h=1:10, v=1:10, col="gray", lty=3)
More information about custom tick intervals in this thread and here for grid alignment.
For posterity, here is the long-winded way of doing it manually:
plot (x = 1:10, y = rnorm (10, 5, 2))
grid (lty = 6, col = "cornsilk2")
xaxp <- par("xaxp")
yaxp <- par("yaxp")
abline(v=seq(xaxp[1], xaxp[2], (xaxp[2]-xaxp[1])/xaxp[3]), lty=6, col = "cornsilk2")
abline(h=seq(yaxp[1], yaxp[2], (yaxp[2]-yaxp[1])/yaxp[3]), lty=6, col = "cornsilk2")
The answer provided here is much more straightforward, although you may dislike the lack of "free space" at each end of the axes. In brief,
The problem is that grid is putting nx grid lines in the user space,
but plot is adding 4% extra space on each side. You can take control
of this. Adding xaxs="i", yaxs="i" to your plot will turn off the
extra space. But then your upper right point will be cut off, so you
need to change the xlim and ylim values and change nx to match