Adding label for last point of line in R plot - r

Consider the following plot:
par(xaxs='i',yaxs='i')
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)
plot(q1, type = "l", lty = 1, lwd = 2, col = "darkolivegreen3", ylim = c(0,4*10^6), xlim = c(1,30), bty = "l")
text(30, q1[30], labels = "text", col = "gray36", cex = 0.8, pos = 4)
I would like to add the label "text" at the right of the last point of the green line (i.e. the point on the line with x = 30).
I tried the code above but the text doesn't show up! Any ideas how to solve that?
Thanks!

By default things in a plot are clipped to the plot region, you are not seeing the text because it has been clipped. You can either use the mtext function to explicitly place the text into the margin. Or if you specify par(xpd=NA) then the clipping will be turned off (well it will still clip to the device region) and the text plotted using the text function will now be plotted extending into the margin. Either way you will probably want to specify some space in the appropriate margin so there is room for the text to be and look nice. See ?par for how to specify the margin and more detail on clipping.

I just realized that this could be done using mtext:
mtext("text", side = 4, at = q1[30], las = 1)

Related

How do I place labels within opaque text boxes at group centroids in ordiellipse?

I'm trying to place labels within opaque text boxes at my group centroids in vegan::ordiellipse().
Code below yields plot below. Note that centroid labels default to plain text with no opaque text box.
library(vegan)
ordiplot(jac_pcoa, main = Trt)
ordiellipse(jac_pcoa,
draw = "polygon",
kind = "se",
groups = pcoa_grps,
col = col_vect,
lwd = 2)
ordiellipse(jac_pcoa, groups = pcoa_grps,
kind = "ehull",
col = col_vect,
lwd = 2,
label = TRUE)
Function vegan::ordispider(), however, formats the labels as I want.
ordiplot(jac_pcoa, main = i)
ordispider(jac_pcoa, groups = pcoa_grps,
col = col_vect,
lwd = 2,
label = TRUE)
How can I achieve labels like those generated by ordispider() when using ordiellipse()?
There is no option to do this directly, but you can trick the function to do what you want: ordiellipse will draw labels on opaque labels with draw = "polygon". Setting col=NULL or omitting the col argument will only draw non-filled ellipses, and the colour of the border line can be set with argument border.

How to change the legend box width when plotting in R

I use the following script to generate a legend in R. But the legend box is too small... how do I increase the box width?
legend("topleft", lty = 1, legend = c("Sub_metering_1","Sub_metering_2","Sub_metering_3"),col = c("black","red","blue"))
You are probably resizing your graph after you plot it and the legend. If that is the case, and you want to keep the box, one option would be to plot the graph, resize it, and then generate the legend. Perhaps a better option would be to size the window to the desired width to start with:
# on Windows, you can use the `windows` function. elsewhere, try quartz or X11
windows(height = 7, width = 3.5)
plot(hp ~ mpg, data = mtcars)
leg <- legend("topleft", lty = 1,
legend = c("Sub_metering_1","Sub_metering_2","Sub_metering_3"),
col = c("black","red","blue"),
#plot = FALSE,
#bty = "n")
)
You can also define exactly where you want the box to fall by providing a pair of x and y coordinates to the legend function. Those values would represent the upper left and bottom right corners of the box. The legend function will actually generate the coordinates for the upper-left hand corner of the box along with the width and height. By default it returns them invisibly, but you can assign them to an object, and If you use the plot = FALSE, option to legend you can capture those coordinates and modify them as you wish without actually plotting the legend.
windows(height = 7, width = 3.5)
plot(hp ~ mpg, data = mtcars)
legend(x = c(9.46, 31), y = c(346.32, 298),
legend = c("Sub_metering_1","Sub_metering_2","Sub_metering_3"),
col = c("black","red","blue"),
lty = 1)
The legend function will actually generate the coordinates for the upper-left hand corner of the box (that's where I got 9.46 and 346.62) along with the width and height of the box. By default it returns them invisibly, but you can assign them to an object, and if you use the plot = FALSE, option to legend you can capture those coordinates and modify them as you wish without actually plotting the legend.
plot(hp ~ mpg, data = mtcars)
leg <- legend("topleft", lty = 1,
legend = c("Sub_metering_1","Sub_metering_2","Sub_metering_3"),
col = c("black","red","blue"),
plot = FALSE)
# adjust as desired
leftx <- leg$rect$left
rightx <- (leg$rect$left + leg$rect$w) * 1.2
topy <- leg$rect$top
bottomy <- (leg$rect$top - leg$rect$h) * 1
# use the new coordinates to define custom
legend(x = c(leftx, rightx), y = c(topy, bottomy), lty = 1,
legend = c("Sub_metering_1","Sub_metering_2","Sub_metering_3"),
col = c("black","red","blue"))
Part of the legend width is determined by the longest width of the labels you use, which is calculated via strwidth. Below an easy example how to halve or double the size by using legend(..., text.width = ...).
plot(1)
text = c("Sub_metering_1","Sub_metering_2","Sub_metering_3")
legend("topleft"
,lty = 1
,legend = text
,col = c("black","red","blue")
)
strwidth(text)
# [1] 0.1734099 0.1734099 0.1734099
# half the length
legend("bottomleft"
,lty = 1
,legend = text
,text.width = strwidth(text)[1]/2
,col = c("black","red","blue")
)
# double the length
legend("center"
,lty = 1
,legend = text
,text.width = strwidth(text)[1]*2
,col = c("black","red","blue")
)

R: how to remove this tiny axis margin in plot

I want to get rid the small margin close to zero on X and Y value (red line on pic), and plot ONLY what is showed in red square.
I tried setting par(mar = rep(0, 4) and xlim=c(0, ...), ylim=c(0, ...) but R still keeps adding this tiny margin. How to get rid of it?
EDIT:
another point of view on my problem:
after running:
require(plotrix)
axisRange <- c(0,500)
plot(NULL, xlim = axisRange, ylim=axisRange)
draw.circle(0, 0, 200, col = "white", border = "red")
I end up with a circle positioned not in "true" 0,0 point:
EDIT2:
Actually what I want to do, is to plot circles of different radius, and save it as an image. That is why I care about the margins.
I end up with something like this (spots on the corners are for the reference):
And should be more like this:
You can set the xaxs and yaxs arguments to "i" as opposed to the default of "r". From the par help page:
Style "r" (regular) first extends the data range by 4 percent at each
end and then finds an axis with pretty labels that fits within the
extended range.
Style "i" (internal) just finds an axis with pretty labels that fits
within the original data range.
library(plotrix)
axisRange <- c(0,500)
par(mar = rep(0,4))
plot(NULL, xlim = axisRange, ylim=axisRange, xaxs = "i", yaxs = "i")
draw.circle(0, 0, 200, col = "white", border = "red")
Gives:

increasing the size of the coloured squares on histogram legends in R

I am trying to increase the size of the coloured squares in the legend on a histogram in R - when I output the PDFs they are too small so it is hard to distinguish the colours. I've searched Google, the R-help Nabble forum and this place, all to no avail. I've also tried several of the commands in the legend documentation.
What do I need to use in the legend() function to increase them? and is it possible to remove the black border around each coloured square to ease viewing?
Here my example:
a<-c(1,1,2,3,3,3,3,4,54,56,2,23,1,3,23)
hist(a)
graphics::legend(x=-1,y=10,c(">0%",">20%",">40%",">60%",">80%"),
x.intersp=1,y.intersp=2,cex=1, bty="n",
fill=c("black","gray50","gray70","gray85","white"))
I wish to change the size of box in the legend?
SOLUTION: from #Ben Bolker
add to the script above the legend function
> source("http://www.math.mcmaster.ca/bolker/R/misc/legendx.R")
then add
> box.cex=c(2,2)
within the legend function
I hacked the source of the legend function to allow a box.cex argument that specifies the relative x and y dimensions of the box. This isn't perfect -- if the expansion is big enough then you have to adjust y.intersp to prevent the fill boxes from overlapping.
source("http://www.math.mcmaster.ca/bolker/R/misc/legendx.R")
a<-c(1,1,2,3,3,3,3,4,54,56,2,23,1,3,23)
cex <- 1
hist(a)
legend("topright",c(">0%",">20%",">40%",">60%",">80%"),
bty="n",
fill=c("black","gray50","gray70","gray85","white"),
box.cex=c(3,3),
y.intersp=2.8)
You can use very thick lines, with rectangular ends.
plot( 1, type = "n", axes = FALSE, xlab = "", ylab = "" ) # Empty plot
par( lend = 1 ) # Rectangular line endings
legend(
"topleft",
c( "Red", "Black" ),
col = c("red", "black"),
lty = 1, lwd = 10
)
It is difficult to mix the option fill and change the size of the box.
But we can have something with options pt.cex and pch without fill options.
a<-c(1,1,2,3,3,3,3,4,54,56,2,23,1,3,23)
par(mfrow=c(1,2))
hist(a)
graphics::legend(x=10,y=10,c(">0%",">20%",">40%",">60%",">80%"),
x.intersp=1,y.intersp=1,cex=c(1),bty="n",
fill=c("black","gray50","gray70","gray85","white"),
# pch=c(24,22,21,23,25),
pt.cex = c(2,2,2,2,5),
lwd=1.5,title='Histo fill option')
hist(a)
graphics::legend(x=10,y=10,c(">0%",">20%",">40%",">60%",">80%"),
x.intersp=1,y.intersp=1,cex=c(1),bty="n",
pch=c(24,22,21,23,25),
pt.cex = c(1,2,3,3,4),
lwd=1.5, title = 'Histo whithout fill ')

R legend issue, symbols of points are masked by lines

Is there a way to draw the lines in such a way that they would start on the side of the points, or allow the symbols to be in foreground?
My solution was to make the symbols bigger and more visible.
Edit 1: it's for plot {graphics} of the R program.
Edit 2: the code per popular request.
legend(2,.4,bty='n', c('sugar','citrus','none'), pch=c('s','c','u'), pt.bg='white',lty= c(1,2,3), lwd=1.5, title="Condition",pt.cex=c(1.5),cex=1.5)
Edit 3: This is solved for plot(type='b') but somehow not for legend.
Thanks for reading!
The only thing I can come up with is to manually finagle the dash lengths until they end up looking the way you want them. For instance, this:
> plot(1,1)
> legend(c("A", "B"), col = 1:2, x = 1, y = .8, lty="99", pch=1:2)
produces the image below.
The lty parameter allows you to specify the lengths of lines and dashes as hex characters. In this case, it's saying to create a line of length 9 then create a space of length 9 then repeat. It looks like 9 is about the best fit to space around a normal pch symbol.
Note that you'd probably need to adjust this depending on the size of the image, symbol, etc. My advice ultimately would be to export the image from R and touch up the image to meet your needs in graphic editing software.
Going with the suggestion by #JeffAllen, here is a way to get what I think you might want. It requires modifying the legend() function to return the position of the points (these are given by x1 and y1 in body(legend)[[46]]).
legend2 <- legend
body(legend2)[[49]] <- quote(
invisible(list(rect = list(w = w, h = h, left = left, top = top),
text = list(x = xt, y = yt), points = list(x = x1, y = y1)))
)
Make a plot:
plot(-100:100, -100:100, type = "b")
While drawing the legend, draw white circles (pch = 21 with pt.bg = 'white') over the lines, and assign the values invisibly returned by legend2() to an object. Note also the changes to pt.lwd and pt.cex.
myLegend <- legend2(1, .8, bty = 'n', c('sugar','citrus','none'), pch = 21,
pt.bg = 'white', pt.lwd = 0, lty = c(1, 2, 3), lwd = 1.5, title = "Condition",
pt.cex = c(1.8), cex = 1.5)
Finally, draw the characters you'd like to use in the legend using points(), supplying the x and y values from the object myLegend.
points(myLegend$points$x, myLegend$points$y, pch = c('s','c','u'), cex = 1.5)
And this should get you something like:
You could also use the filled points offered by R (pch=21:25) and specify the fill color using pc.bg which gets passed to the points call when creating a legend.
plot(1,1)
legend(c("A", "B"), col = 1:2, x = 1, y = .8, lty=1, pt.bg=1:2, pch=21:22)
generates the following:

Resources