Change font-size in legend - r

I have a legend in my plot, but I'm trying to increase the font size so it fit the legend-box. When I try to increase the cex as defined below. The box gets bigger, while the text is still small.
Code:
legend(0,16, c("Available vCPUs", "Added vCPUs (1 per iteration ) "),
col=c('red', 'black'), cex=0.39, lty=1:1, lwd=2)
Excerpt from plot:

First approach:
Try to set the font size before to plot the legend.
x <- y <- rnorm(100, 0, 1)
plot(x, y, type = "n")
## here you set the font size default to `x`, in this example 0.5
## save defaults in `op`
op <- par(cex = 0.5)
legend("topright", legend = "foo legend", pch = 1, bty = "n")
## here you set cexto 1.5
## save new defaults in `op`
op <- par(cex = 1.5)
legend("topright", legend = "foo legend", pch = 1, bty = "n")
Second approach:
Holding the pt.cex parameter to 1, while trying different values for cex inside the legend call. Remember to delete op.
x <- rnorm(100, 10, 4)
y <- rnorm(100, 10, 4)
plot(x, y, type = "n")
## I tried to feed cex with 1.5 and 0.5. The font size changes while the points remain unchanged.
legend("topleft", "Legend", cex=0.5, pch=1, pt.cex = 1)

You can use cex to determine font size, use bty='n' to indicate no lines around the legend, then draw a rectangle separately on the graph with rect(). For example:
with(data, legend(-10,7, legend=c("Name_of_Legend"), bty = 'n', col=c("red"), lty=0, pch=20, cex=0.75))
with(data, rect(-10,6.2,-3,7))

I think you can try using the
y.intersp in legend, when the intervals between different text lines are reduced, you could increase text size without changing the size of legend box.
legend(0,16, c("Available vCPUs","Added vCPUs (1 per iteration )
"),col=c('red','black'),cex=0.39,lty=1:1,lwd=2, y.intersp = 0.3)

Related

Label font size in PredictorEffects plot in R

I am plotting an ordinal regression plot with the PredictorEffects function, where I need to increase the font size of my labels. I was using cex function to do the same, but I cannot change the font size of x-axis.
Here are the codes:
m1 = polr(as.factor(views)~ caste, data = data, Hess=TRUE)
plot(predictorEffects(m1), lines=list(multiline=TRUE), xlab = list("Caste", cex = 2),
ylab= list("attitude probability", cex = 2), main=FALSE)
The cex function is working for y-axis but not for x-axis
Try using the cex.lab function:
The magnification to be used for x and y labels relative to the
current setting of cex.
Here an example no cex.lab:
x <- rnorm(100)
plot(x, main = "plot")
Output:
Here cex.lab=2:
plot(x, main = "plot", cex.lab = 2)
Output:

R plot legend: Reduce space between legend columns

I am using vegan library to make some plots, with this code:
raremax <- min(colSums(mydata))
col <- palette()
lty <- c("solid", "dashed", "longdash", "dotdash")
pars <- expand.grid(col = col, lty = lty, stringsAsFactors = FALSE)
out <- with(pars[1:18, ], rarecurve(mydata, step = 100, sample = raremax,
cex =0.6, ylab="OTUs", label=F, col=col, lty=lty, lwd=2))
Then I add a legend using this code:
legend("bottomright", names(mydata), col=pars[1:18,1], lty= pars[1:18,2],
lwd=2, cex=0.5, xjust=1, ncol=2, x.intersp=0.5, y.intersp=0.5, bg="white")
The resulting graph looks like this:
I would like to reduce the space between legend columns, also reducing the size of the legend box, but I can't find a way to do that.
Anyone could provide me some help?
A combination of the legend() parameters "x.intersp" and "text.width" should be helpful.
Decreasing "x.intersp" (default value = 1, for me 0.25 looked good) should move your the legend labels closer to their respective points. Decreasing "text.width" (default value=NULL, for me 0.045 looked good) moves the columns closer together.

Align grid() to plot ticks

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."

placing legend outside a dynamically changing plot R

In my R code below, I have two situations each resulting in a different plot depending on S being larger OR smaller than 1. I was wondering how I can take out (move up) the current legend and put it above the plot at the same place for either of the resulting plots?
Note: Due to Y axis being on log-scale, I have used 10^par('usr')[4] but I need to add a number to 10^par('usr')[4] (i.e., (10^par('usr'))[4] + a number) such that "this number" puts the legend in the exact same place above either of the resulting plots?
Here is the R code:
S <- 0.25 ### !!! Change this to "24" and see how another plot will appear !!! ###
Ur <- c(0.25, 24, 16)
if(S>=1){
plot(1, 1, type = "n", xlim = c(0,1.5), ylim = c(1/3, 100), log="y", bty="n", ann=F, axes=F, xaxs="i")
axis(side=1, at = seq(0,1.5,.25),labels = c("0",".25",".5",".75","1","1.25","1.5"))
axis(side=2, at = c(1/3, 1, 3, 10, 30, 100),labels = c("1/3", "1", "3", "10", "30", "100"),las=1)
}else{
plot(1, 1, type = "n", xlim = c(0,1.5), ylim = c(.01, 3), log="y", bty="n", ann=F ,axes=F, xaxs="i")
axis(side=1, at = seq(0,1.5,.25),labels = c("0",".25",".5",".75","1","1.25","1.5"))
axis(side=2, at = c(.01, 1/30, 1/10, 1/3, 1, 3),labels = c("1/100", "1/30", "1/10", "1/3", "1", "3"),las=1)
}
legend(0, (10^par("usr"))[4], bquote(paste("Selected Prior: ",bold('PN'[10])," = ", .(round(S,3)))), ## Legend
pch = 21,cex=2,pt.bg="green", col="red", pt.cex=2.8, bty="n")
You can use the inset argument in legend.To do so, you need to use legend location as a word. In your case, "topleft". This way, you do not need to provide specific location based on your "y".
The inset argument allows you to offset the legend. In the present case, the y is offset by -0.03.
I also use par(xpd=TRUE)to expand the allowed plotting space. Finally, I also changed the font size to produce the following charts.
par(xpd=TRUE)
legend("topleft", legend=bquote(paste("Selected Prior: ",bold('PN'[10])," = ", .(round(S,3)))), ## Legend
pch = 21,cex=1,pt.bg="green", col="red", pt.cex=2, bty="n", inset=c(0,-0.03))

trying to remove all margins so that plot region comprises the entire graphic

I am trying to remove all margins and the "figure region" of a plot in R, so that the plot region comprises the entire graphic device. I thought the code below would do it, but there is still a border around my plot (wider on left/bottom, thinner on top/right). Thanks
par(oma=c(0, 0, 0, 0))
par(mar=c(0, 0, 0, 0))
par(plt=c(0, 1, 0, 1))
Thought I would add a picture to show my progress. The xaxs and yaxs removed nearly all border from the top and right- there is still a border on the left and bottom.
The relevant portion of my script is below.
png("Test.png",
width = 256, height = 256,
units = "px", pointsize = 6.4,
bg = "black", res = NA)
par(mar=c(0, 0, 0, 0), xaxs='i', yaxs='i')
smoothScatter(lhb$px, lhb$pz, nrpoints=0, xlim=c(-3,3), ylim=c(0,5),
main="", xlab="", ylab="", axes=FALSE,
colramp=colorRampPalette(c("black", "#202020", "#736AFF", "cyan", "yellow", "#F87431", "#FF7F00", "red", "#7E2217"))
)
segments(.83, 1.597, .83, 3.436, col = par("fg"), lty = par("lty"), lwd = par("lwd"))
segments(-.83, 1.597, -.83, 3.436, col = par("fg"), lty = par("lty"), lwd = par("lwd"))
segments(-.83, 3.436, .83, 3.436, col = par("fg"), lty = par("lty"), lwd = par("lwd"))
segments(-.83, 1.597, .83, 1.597, col = par("fg"), lty = par("lty"), lwd = par("lwd"))
dev.off()
One issue is fundamentally not getting what plt does. From ?par we have:
‘plt’ A vector of the form ‘c(x1, x2, y1, y2)’ giving the
coordinates of the plot region as fractions of the current
figure region.
So your plot region is of zero size if you do par(plt=c(1, 1, 1, 1)), so that doesn't seem to be the way to go. This is because the figure region contains the plot region.
This plot seems to cover the entire region, without any margins:
op <- par(mar = rep(0, 4))
plot(1:10)
par(op)
it covers it so well you can't see the axes or the box:
This assumes the default for 0 outer margin (oma). Is this what you were looking for?
We can see that just adjusting the plot margins, as above, we also change the plt parameter as a side effect:
> par("plt")
[1] 0.1173174 0.9399106 0.1457273 0.8828467
> op <- par(mar = rep(0, 4))
> par("plt")
[1] 0 1 0 1
> par(op)
> par("plt")
[1] 0.1173174 0.9399106 0.1457273 0.8828467
indicating that simply setting the plot margins is sufficient to get a plot/figure region encompassing the entire device.
Of course, there is still a bit of internal padding that insures the ranges of the axes are slightly large than the range of the data in both the x and y coordinates. But you can control this with xaxs and yaxs --- see ?par
Update: As the OP has shown the sort of figure they are trying to produce without margins, I can provide a reproducible example:
set.seed(1)
dat <- matrix(rnorm(100*100), ncol = 100, nrow = 100)
layout(matrix(1:2, ncol = 2))
image(dat)
op <- par(mar = rep(0, 4))
image(dat)
par(op)
layout(1)
which gives for comparison:
and showing just the full plotting region:
Try setting the clip region parameter 'xpd' to NA ( clipped to device).
par(xpd = NA)

Resources