I know I can create a plot with line and dots using the type = "o" argument in the plot command. I would like some more control over this -- I want to be able to draw the "o" as full dots, with black border and fill-in color of my choice, of customized size and of a different color than the line. Same for the line, I want to make it thicker, and of my choice of color. How would I go on about doing that?
What I found until now is just a plain
plot(y, type= "o")
which is too poor for my needs.
I am not interested in using ggplot, but instead use the internal plot library of R.
Any help appreciated.
All the information you need should be present in ?plot and ?points, as suggested by #BenBolker. In particular, you want to be using pch=21, and specifying background colour with the bg argument, size with cex, and line width with lwd.
If you want the line to be a different thickness to the point borders, you need to plot the line first, and then overlay the points.
For example:
y <- sample(10)
plot(y, lwd=6, type='l')
points(y, bg='tomato2', pch=21, cex=3, lwd=3) # tomato2 is a personal fave
You could also provide a vector of lwd, cex and col to the points call:
plot(y, lwd=6, type='l')
points(y, bg=rainbow(10), pch=21, cex=seq(1, by=0.2, length.out=10),
lwd=seq(2, by=1, length.out=10))
You could use layering (I don't work in base too much any more as a social researcher I love the facet_grid of ggplot, so there may be a better way) as in:
x <- sort(rnorm(25))
y <- sort(rnorm(25))
z <- as.factor(sample(LETTERS[1:5], 25, r=TRUE))
plot(x, y, pch = 19, cex = 1.3)
par(new = TRUE)
plot(x, y, pch = 19, cex = 1, col = z)
Which gives you:
Related
I'm tinkering with cex options in base R plots to resize my plot for a presentation slide. I seem to be able to tweak most size aspects, but I notice the outline color of my pch point is not getting any bolder/thicker when the plot point becomes larger. So the larger the plot point, the less noticeable the outline color.
Found many websites (& SO posts) on various cex options (cex, cex.main, cex.sub, cex.axis, cex.lab), but none seem to be adjusting the pch plot point.
I'm aware that only certain pch symbols (21 to 25) can be used with fill color and outline. My sample code uses 21 (circle).
data("mtcars") # test data
summary(mtcars[c("hp","mpg")]) # to find on min & max values to set plot limits
# set general features used for multiple plots
par(bg="blue", fg="red", col="yellow", col.axis="white", col.lab="white", bty="n", cex=1.5)
# test plot to illustrate, cex used here to further adjust plot points from par setting
plot(mtcars$hp, mtcars$mpg, ylim=c(10, 35), xlim=c(50, 340), pch=21, bg="red", cex=2)
Am I missing something about cex or is there a different solution without turning to ggplot? I'm not adverse to ggplot if there is an option, but I'd like to see if it can be done in base R.
You need to specify lwd to change the border thickness of pch symbol
plot(1:10, 1:10, pch = 21, cex = 3, lwd = 1:10)
I'm looking to implement EXACTLY this, but using plot() instead of ggplot2. There is even a reply on the blog by someone saying they did this with plot, but the link to their code is dead. I'm literally trying to do the exact same thing. I've downloaded data from FRED using quantmod's getSymbols(), and I have that data in a df, which I'm plotting with plot(). The x-axis are dates, and I want to change the background color based on a specific set of dates. Any ideas or hints how I can do this with plot?
Thank you!
Based on this question: R: change background color of plot for specific area only (based on x-values)
## plotting area with no axes
plot(unrate.df, type = "n")
lim <- par("usr")
## adding one rectangle
for (i in 1:nrow(recessions.trim)) {
rect(recessions.trim[i, 1], lim[3],
recessions.trim[i, 2], lim[4], border = "pink", col = "pink")
}
## adding the data
lines(unrate.df)
box()
You can use this:
plot(unrate.df, type="n")
makeRectangles(recessions.trim, col="pink", alpha=0.5)
lines(unrate.df)
grid()
where the function makeRectangles is defined as:
makeRectangles = function(x, col, alpha=1, border=NA, ...) {
col = col2rgb(col=col, alpha=FALSE)
col = rgb(red=col[1], green=col[2], blue=col[3],
alpha=floor(255*alpha) , maxColorValue=255)
rect(x[,1], par("usr")[3], x[,2], par("usr")[4], col=col, border=border, ...)
return(invisible())
}
I have multiple time series data plots and I need an horizontal line in each plot but with different horizontal values (es. 1st plot: h=50, 2nd plot: h=48...).
I tried abline(h=50... and I get the horizontal line in each plot.
I tried abline(h=c(50,48... and I get multilple horizontal lines in each plot.
I can't figure out how to get the plot.zoo index in order to plot h=50 in the 1st plot, h=48 in the 2nd plot and so on.
library(xts)
data(sample_matrix)
x <- as.xts(sample_matrix)
# plot with single line
my.panel <- function(x, ...) {
lines(x, ...)
abline(h=50, col = "red", lty="solid", lwd=1.5 )
}
plot.zoo(x, main="title",
plot.type="multiple", type="o", lwd=1.5, col="blue",
panel=my.panel)
# plot multiple lines in all plots
my.panel <- function(x, ...) {
lines(x, ...)
abline(h=c(50,50,48,50), col = "red", lty="solid", lwd=1.5 )}
plot.zoo(x, main="title",
plot.type="multiple", type="o", lwd=1.5, col="blue",
panel=my.panel)
To customize single panels in a multipanel plot is not thoroughly described in the actual ?plot.zoo text. In the 'Details' section you find:
"In the case of a custom panel the panel can reference parent.frame$panel.number in order to determine which frame the panel is being called from. See examples.". And there are quite a few examples. Using them as template, I found that this could be a way to call separate panels, and draw a separate hline in each.
Update. Thanks to #G. Grothendieck for an edit that made the code much cleaner!
# create values for hline, one for each panel
hlines <- c(50, 50, 48, 50)
# panel function that loops over panels
my.panel <- function(x, ...) {
lines(x, ...)
panel.number <- parent.frame()$panel.number
abline(h = hlines[panel.number], col = "red", lty = "solid", lwd = 1.5)
}
plot.zoo(x, main = "title", type = "o", lwd = 1.5, col = "blue", panel = my.panel)
I'm generating numerous plots with xlim and ylim values that I'm calculating on a per-plot basis. I want to put my legend outside the plot area (just above the box around the actual plot), but I can't figure out how to get the maximum y-value of the box around my plot area.
Is there a method for even doing this? I can move the legend where I want it by manually changing the legend() x and y values, but this takes a LONG time for the amount of graphs I'm creating.
Thanks!
-JM
Here's a basic example illustrating what I think you're looking for using one of the code examples from ?legend.
#Construct some data and start the plot
x <- 0:64/64
y <- sin(3*pi*x)
plot(x, y, type="l", col="blue")
points(x, y, pch=21, bg="white")
#Grab the plotting region dimensions
rng <- par("usr")
#Call your legend with plot = FALSE to get its dimensions
lg <- legend(rng[1],rng[2], "sin(c x)", pch=21,
pt.bg="white", lty=1, col = "blue",plot = FALSE)
#Once you have the dimensions in lg, use them to adjust
# the legend position
#Note the use of xpd = NA to allow plotting outside plotting region
legend(rng[1],rng[4] + lg$rect$h, "sin(c x)", pch=21,
pt.bg="white", lty=1, col = "blue",plot = TRUE, xpd = NA)
The command par('usr') will return the coordinates of the bounding box, but you can also use the grconvertX and grconvertY functions. A simple example:
plot(1:10)
par(xpd=NA)
legend(par('usr')[1], par('usr')[4], yjust=0, legend='anything', pch=1)
legend( grconvertX(1, from='npc'), grconvertY(1, from='npc'), yjust=0,
xjust=1, legend='something', lty=1)
The oma, omd, and omi arguments of par() control boundaries and margins of plots - they can be queried using par()$omd (etc). and set (if needed) using par(oma=c()) (where the vector can have up to 4 values - see ?par)
This is perhaps very basic, but I just can't seem to find a working solution:
I'm building a boxplot with custom axes using the 'boxplot()' function in R, and I'd like to have thin grey lines for reference across the y-tick intervals, something like:
boxplot("MyDataTable", ylim=ylim, axes=FALSE, col=312, notch=TRUE)
axis(2, lwd=1.5, at=ytk, las=2, tck=-0.02, cex.axis=0.75, font=2)
abline(h=yln, lty=1.5, lwd=0.5, col=336)
When this prints out (to pdf, in my case), the thin grey lines overlap the boxplot's boxes and whiskers.
How can I have the same plot with the graphed boxes and whiskers being in the foreground...?
One way is just to repeat the boxplot call by adding it to the existing plot, so the horizontal lines become background.
For example:
boxplot(count ~ spray, data = InsectSprays, col = "lightgray", main = "plot title")
abline(h = 1:25, lty=1.5, lwd=0.5, col=336)
boxplot(count ~ spray, data = InsectSprays, col = "lightgray", add = TRUE)
Since you also need interaction with the axis ticks, you might find something similar works there as well but your code is not reproducible, so we can only guess at the actual effect you want to see.
Simple boxplot, overplotted on horizontal lines http://beta1.opencpu.org/R/call/store:tmp/a2884b758f76d5c808e0f9751c35ad74/png?main=%22plot%20title%22