Legend objects closer between them in R - r

I have to plot the following graph in R:
library(TTR)
x.date<-seq(1,num.years,by=20)
x.axis<-list(x1="1900",x2="1920",x3="1940",x4="1960",x5="1980",x6="2000")
plot(Annual.Mean.1, type="l",col="gray48",xaxt="n", xlab="Years",
ylab="Temperature")
grid()
axis(1,x.date,x.axis)
SMA.1<-SMA(Annual.Mean.1,n=10
par(new=TRUE)
lines(SMA.1,col="red",type="l",lwd="2",xaxt="n",yaxt="n",ann=FALSE)
SMA.2<-SMA(Annual.Mean.1,n=15)
par(new=TRUE)
lines(SMA.2,col="mediumpurple",type="l",lwd="2",xaxt="n",yaxt="n",ann=FALSE)
SMA.3<-SMA(Annual.Mean.1,n=20)
lines(SMA.3,col="blue",type="l",lwd="2",xaxt="n",yaxt="n",ann=FALSE)
legend("topleft",legend=c("Average Temperature","SMA 10 years","SMA 15 years","SMA 20 Years"),
text.col=c("black","red","mediumpurple","blue"),col=c("gray48","red","mediumpurple","blue"),
cex=0.7,lty=c(1,1,1,1))
The output is this:
In the above plot, the rectangle which contain the legend is very big; i would like to obtain a smaller rectangle, like in the below plot:
How to do this?
UPDATE
As suggested in the comments, I have modified my code, in order to make it reproducible by anyone:
library(TTR)
set.seed(1)
x.date<-seq(1,111,by=20)
x.axis<-list(x1="1900",x2="1920",x3="1940",x4="1960",x5="1980",x6="2000")
data<-runif(111,-3,3)
plot(data, type="l",col="gray48",xaxt="n",xlab="Years",
ylab="Temperature")
grid()
axis(1,x.date,x.axis)
SMA.1<-SMA(data,n=10)
par(new=TRUE)
lines(SMA.1,col="red",type="l",lwd="2",xaxt="n",yaxt="n",ann=FALSE)
SMA.2<-SMA(data,n=15)
par(new=TRUE)
lines(SMA.2,col="mediumpurple",type="l",lwd="2",xaxt="n",yaxt="n",ann=FALSE)
SMA.3<-SMA(data,n=20)
lines(SMA.3,col="blue",type="l",lwd="2",xaxt="n",yaxt="n",ann=FALSE)
legend("topleft",legend=c("Average Temperature","SMA 10 years","SMA 15 years","SMA 20 Years"),
text.col=c("black","red","mediumpurple","blue"),col=c("gray48","red","mediumpurple","blue"),
cex=0.7,lty=c(1,1,1,1))
I still having the same problem as explained above.

Reduce the value of your cex parameter in the legend call. You have it at cex=0.7. Try 0.6 or 0.5 (or lower) until you find the best size.
If that doesn't work, another approach is to just remove the box around the legend altogether with parameter bty = "n". If the background of the legend is blocking the lines in the graph, move the legend command up in your code so that it is drawn first and the lines are drawn over top of it.

Related

Legend dynamically populated

I have plotted a histogram in R and marked quantiles using abline() in vertical intervals. However, I want to plot a legend that shows the corresponding values to the quantiles together with the quantile interval itself.
The current legend is almost there as you can see if you run the example code below. But I can't seem to succeed at aligning the legend interval with its corresponding value and colored line symbol. I tried to use a data.frame() to achieve this but it didn't work out.
Any tips or suggestions will be very much appreciated.
x<-1:100
quantiles_x<-quantile(x)
hist(x)
abline(v=quantiles_x, col=c("blue", "green","red","yellow","black"))
legend('topright', legend=c(names(quantiles_x), levels(factor(quantiles_x))), lwd=1, col=c("blue","green","red","yellow","black"))
Something like this??
x<-1:100
quantiles_x<-quantile(x)
hist(x)
abline(v=quantiles_x, col=c("blue", "green","red","yellow","black"))
labels <- paste(names(quantiles_x), "[",quantiles_x,"]")
legend('topright', legend=labels, lwd=1,
col=c("blue","green","red","yellow","black"))

R-plot a centered legend at outer margins of multiple plots

I want to plot a centered legend outside of the plotting area in a device having multiple plots. There has been many questions (with slight variations) asked in SO about changing the position of legend in a R plot.
For example:
1) R - Common title and legend for combined plots
2) Common legend for multiple plots in R
3) Plot a legend outside of the plotting area in base graphics?
etc.
Now what I understood from the above questions is that I got to set the option xpd = T or xpd = NAto plot legends at the outer margins. However when I try this, it somehow does not work for me ..
par(mfrow=c(1,2),oma=c(0,3,0,0),xpd=TRUE)
plot(c(5,10),col=c("red","blue"),pch=20,cex=2,bty="n",xlab="",ylab="")
barplot(c(5,10),col=c("red","blue"))
mtext(text="My two plots",side=3,cex=2,outer=TRUE,line=-3)
legend("top",legend=c("A", "B"),fill=c("red","blue"),ncol=2,xpd=NA,bty="n") # Option 1
legend(x=0.01,y=11,legend=c("A", "B"),fill=c("red","blue"),ncol=2,xpd=TRUE,bty="n") # Option 2
Now my question is, how does xpd exactly work ? as I am unable to figure out why shouldn't the legend not be placed outside the plot area with xpd=T.
I apologize in advance if some consider this as a duplicate of the above questions !!
Help is much appreciated
Ashwin
Option #1 is likely the route you should take, with xpd=NA. It does not automatically place the legend in the outer margins, but it allows you to place the legend anywhere you want. So, for example, you could use this code to place the legend at the top of the page, approximately centered.
legend(x=-1.6, y=11.6, legend=c("A", "B"), fill=c("red", "blue"), ncol=2, xpd=NA, bty="n")
I chose these x and y values by trial and error. But, you could define a function that overlays a single (invisible) plot on top of the ones you created. Then you can use legend("top", ...). For example
reset <- function() {
par(mfrow=c(1, 1), oma=rep(0, 4), mar=rep(0, 4), new=TRUE)
plot(0:1, 0:1, type="n", xlab="", ylab="", axes=FALSE)
}
reset()
legend("top", legend=c("A", "B"), fill=c("red", "blue"), ncol=2, bty="n")
I also had a hard time to get coordinates on the margins. I think I found a solution, you can specify coordinates for the legend using:
getCoords() function.
Look also to legend_margin function from plotfunctions package.
So combining the solution from Jean V. Adams with one of these functions should get you there.
Hope that works :)

Y-axis values does not display correctly on my gap.boxplot in R

This is my script and the graph produced. I have made a gap between 7-29.8. But How can I display the y-axis values at 7 and 30? The axis only shows 1-6, instead of 0-7 , 30 as intended.
gap.boxplot(Km, gap=list(top=c(7,30), bottom=c(NA,NA), axis(side=2, at=c(0,29.8), labels= F)),
ylim=c(0,30), axis.labels=T, ylab="Km (mM)", plot=T, axe=T,
col=c("red","blue","black"))
abline(h=seq(6.99,7.157,.001), col="white")
axis.break(2, 7.1,style="slash")
You can call the axis function again to plot the marks at c(0:7,30)
axis(2,c(0:7,30)
But because you have a gap between 7 and 30, anything beyond 7 will have to be shifted in the plot. In general, a mark at position y will have to be moved downwards to y-gap.width, or y-(30-7) in your case.
So you can do this to plot your marks:
axis(2, labels=c(0:7,30), at=c(0:7,30-(30-7)))
It's hard to replicate the plot without example data. But I think this worth a try and should work.
axis(2,labels=c(0:7), at=c(0:7)) # build first gap marker '7'
then separately add the second gap marker
axis(2, labels=c(30), at=7*(1+0.01)) # the interval (0.01) could be different, test to find the best one to fit your plot

Legend box width not correct when using par

I have the problem , that my legend is too large, my code:
par(mfrow=c(1,2))
hist(alvsloss,breaks = 100, freq=F,main="Histogramm,
density curve (gaussian kernel) \n and fitted normal distribution of Allianz simple losses ",xlim=c(-0.15,0.15),xlab="loss",ylab="density",cex.axis=1.2,cex.lab=1.2)
lines(density(alvsloss), col="black", lwd=2)
curve(dnorm(x, mean = mean(alvsloss), sd = sd(alvsloss)), add=TRUE, col="black",lwd=2,lty="dotted")
legend(-0.155, 30, c("(Gaussian) Kernel density","fitted normal distribution"),lwd=2, cex=0.8,
col=c("black","black"), lty=1:2)
qqnorm(alvsloss,main="normal QQ Plot",cex.axis=1.2,cex.lab=1.2)
qqline(alvsloss)
This gives the following picture:
The problem is, that the legend on the left is too big, how can I control the width of the box? The box is way too large.
data can be found here: http://uploadeasy.net/upload/ocafq.rar
The white space on the right of you legend tells me that you manually widened your plot window. Legends do not scale well when it comes to manual re-sizing.
The solution is opening a plot of the exact size you need before plotting. In Windows, this is done with windows(width=10, height=8). Units are in inches. The surrounding box should now be tighter with the text.
If this is still not satisfactory, you should try:
Reducing the font size of the legend cex=0.7
Removing the box around the legend bty = "n" and using \n to
split your legend onto several lines
You can put your legend even more on the left using "topleft"
instead of coordinates
Here's how I would do it:
legend("topleft",
legend=c("(Gaussian)\nKernel\ndensity","Fitted\nnormal\ndistribution\n"),
bty = "n",lwd=2, cex=0.7, col=c("black","black"), lty=1:2)

change look-and-feel of plot to resemble hist

I used the information from this post to create a histogram with logarithmic scale:
Histogram with Logarithmic Scale
However, the output from plot looks nothing like the output from hist. Does anyone know how to configure the output from plot to resemble the output from hist? Thanks for the help.
A simplified, reproducible version of the linked answer is
x <- rlnorm(1000)
hx <- hist(x, plot=FALSE)
plot(hx$counts, type="h", log="y", lwd=10, lend="square")
To get the axes looking more "hist-like", replace the last line with
plot(hx$counts, type="h", log="y", lwd=10, lend="square", axes = FALSE)
Axis(side=1)
Axis(side=2)
Getting the bars to join up is going to be a nightmare using this method. I suggest using trial and error with values of lwd (in this example, 34 is somewhere close to looking right), or learning to use lattice or ggplot.
EDIT:
You can't set a border colour, because the bars aren't really rectangles – they are just fat lines. We can fake the border effect by drawing slightly thinner lines over the top. The updated code is
par(lend="square")
bordercol <- "blue"
fillcol <- "pink"
linewidth <- 24
plot(hx$counts, type="h", log="y", lwd=linewidth, col=bordercol, axes = FALSE)
lines(hx$counts, type="h", lwd=linewidth-2, col=fillcol)
Axis(side=1)
Axis(side=2)
How about using ggplot2?
x <- rnorm(1000)
qplot(x) + scale_y_log10()
But I agree with Hadley's comment on the other post that having a histogram with a log scale seems weird to me =).

Resources