I am plotting several regression lines, distinguished by setting lty, into one graph in R by using the abline command.
Now, I am now trying to add a legend to the plot to help readers interpret it. It's supposed to be a very basic legend:
Linetype X = Variable 1
Linetype Y = Variable 2, etc.
Now the documentation on legend() makes total sense to me, but I have only succeeded in writing out one legend at a time.
Is there any way I can iteratively build this legend? I.e. add
linetype and variable to a blank legend while plotting?
Or do I have to collect all the info and write it after the plotting
is done? If so, what would be the most elegant way to do this?
It would be great if I could rely on standard packages for this to make the code more portable.
Apparently there are ways for doing this in Matlab, but I could not find anything for R.
Here is my code:
cols=c(0:length(v))
count=1
for (v in variables)
{
...
lmodel=lm(v~x);
abline(lmodel, lty=cols[count]);
count=count+1
...
}
}
Any help is much appreciated!
This minimal working example of collecting the legend text from all repetitions of your loop should be easy to adapt for your problem:
# dummy plot
plot(iris[,1:2])
# empty legend text
legend_text <- c()
for (v in 1:4) {
abline(v,0, col = v, lty = v)
# add next legend text
legend_text <- c(legend_text, v)
}
# plot legend once
legend('topright', legend = legend_text, lty=1:4, col=1:4)
One more thing: if you run into problems with using a vector, consider using list() instead.
Related
I have a graph in igraph with a vertex size that is coded for a value.
I wish to add a legend with symbols (points in my case) with different sizes.
I tried the following code
require(igraph)
er_graph <- erdos.renyi.game(100, 5/100)
value<-runif(100)
n<-6
size_vec<-seq_len(n)
sizeCut<-cut(value,n)
vertex.size<-size_vec[sizeCut]
plot(er_graph, vertex.label=NA, vertex.size=vertex.size)
legend('topleft',legend=levels(sizeCut),pt.cex=size_vec,col='black')
but end with legend without symbols
see example
Any sugestions how I go about this?
You should set pch to some value to indicate which character you want to use for the bullets (see ?points to check the possible values).
Also, you should scale the pt.cex values in order to make the bullets not too big for the legend, and use pt.bg to set the background color of the bullets, e.g.
# scaled between 1 and 2
scaled <- 1 + ((2-1) * (size_vec - min(size_vec) ) / ( max(size_vec) - min(size_vec) ) )
legend('topleft',legend=levels(sizeCut),pt.cex=scaled,col='black',pch=21, pt.bg='orange')
EDIT :
Unfortunately, calculating the right sizes of the bullets is not easy; a possible workaround is plotting white bullets then manually add the vertices to the legend in the same way they are plotted inside the plot.igraph function :
# N.B. /200 is taken from plot.igraph source code
a <- legend('topleft',legend=levels(sizeCut),pt.cex=size_vec/200,col='white',
pch=21, pt.bg='white')
x <- (a$text$x + a$rect$left) / 2
y <- a$text$y
symbols(x,y,circles=size_vec/200,inches=FALSE,add=TRUE,bg='orange')
Disclaimer: this code heavily relies on the source code of plot.igraph function that might be changed in a future version of igraph. Probably you should search for another plot function for igraph which natively allows to add a legend.
Anyone looking at this who wants a continuous scale for node sizes instead of a discrete scale then this is the code you need to do it:
require(igraph)
er_graph <- erdos.renyi.game(100, 5/100)
value<-runif(100)
sizeCut<- c(0.2,0.4,0.6,0.8,1.0)
sizeCutScale <- sizeCut*10
vertex.size<-value*10
plot(er_graph, vertex.label=NA, vertex.size=vertex.size)
legend('topleft',legend=unique(sizeCut),pt.cex= sizeCutScale,col='black')
a <- legend('topleft',legend=unique(sizeCut),pt.cex=sizeCutScale/200,col='white',
pch=21, pt.bg='white')
x <- (a$text$x + a$rect$left) / 2
y <- a$text$y
symbols(x,y,circles=sizeCutScale/200,inches=FALSE,add=TRUE,bg='orange')
I'm new to R. Previously, I've been able to overlay 2 separate plots that were of the same kind, p1 and p2, using plot (p1); plot (p2, add=T).
I'm struggling with the definition of factors when overlaying a barplot with a point plot showing all individual points.
I can individually plot the barplot as I want it. The point plot looks like I want it, but I realize I'm using an incorrect definition of phase as numerical to force R plot to display each value, rather than default to a boxplot (like when I use plot(my.df$cond, my.df$val).
Any tips on defining my variable types correctly or whether I'm using the correct barplot and plot functions, would be greatly appreciated. Thank you so much.
shpad <- c(1,2,5,6,1,2,5,6,1,2,5,6,1,2,5,6)
my.df <- data.frame(val=c(0.0738,0.0518,0.002,0.0397,0.1452,0.1152,0.1774,0.0658,0.0218,0.0497,-0.0296,0.0653,0.0848,0.1296,0.1416,0.0923,
phase=c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
sub=c(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4),
cond=c("NsNm", "NsNm", "NsNm", "NsNm", "NsLm", "NsLm", "NsLm", "NsLm", "LsNm", "LsNm", "LsNm", "LsNm", "LsLm", "LsLm", "LsLm", "LsLm"))
avg <-tapply(my.df$val, my.df$phase, mean)
barplot(avg, border=NA, names.arg=c("NsNm", "NsLm", "LsNm", "LsLm"),col=c("blue","darkblue","red", "darkred"),ylab = "score",ylim=c(-0.03,0.25))
plot(my.df$phase, my.df$val, type="p", ylim=c(-0.03,0.25), ylab = "score", pch=shpad)
tl;dr: problem is that if instead of the last line, I have plot(my.df$phase, my.df$val, type="p", ylim=c(-0.03,0.25), ylab = "score", pch=shpad, add=T), the formats are incongruent.
Alright, so, I've tried for a bit to accomplish what you wanted, but the best I could do with the base plotting system is this:
Which is accomplished purely by your lines of code above except for the last line, which I replaced with
points(my.df$phase,my.df$val,type="p",pch=shpad)
However, I think you can do much better, if you want to keep the same kind of plot, using the ggplot2 library. Using this code:
library('ggplot2')
new.df <- data.frame(avg,phase=levels(factor(phase)))
ggplot(new.df) +
geom_bar(stat="identity",aes(x=levels(phase),y=avg, fill=c("NsNm","NsLm","LsNm","LsLm")))+
geom_point(aes(x=my.df$phase,y=my.df$val,shape=factor(shpad))) +
scale_x_discrete(name="Type",labels=c("NsNm","NsLm","LsNm","LsLm")) +
ylab("Score")
you can make this chart:
I didn't adjust the coloring and the point types and the legend titles (not sure how important they are, but those can be fiddled with). However, you can see this probably produces the result you were aiming for.
My question is that I want to add the categorical variables' legends onto the graph but somehow when I used "topright", it did not work for me (see the image below). Basically my idea is to fill the blank area with the legends for my categorical variables on the side of the heatmap. My codes look like
heatmap.3(performance, Colv =NA,RowSideColors=row_annotation,col=my_palette)
par(lend = 1) # square line ends for the color legend
legend("topright", # location of the legend on the heatmap plot
legend = c("category1", "category2", "category3"), # category labels
col = c("gray", "blue", "black"), # color key
lty= 1, # line style
lwd = 10 # line width
)
Also I want to put multiple legend onto the plot but don't know how to specify their positions using x and y as there are no coordinates in my plot.
Thank you so much!
A simple fix to your problem would be to use the option inset=# (where # is some floating point number with a comma after it) following your "topright" specification after its respective comma, which would indicate how to place your legend relative to your graph.
Instead of specifying the default position "topright", perhaps you may want to try restructuring your code in a more personally customized manner, namely utilizing an x-y axis approach, such as for instance use :
dev.new(xpos=#,ypos=#)
Or you may also consider using:
legend.position=c(#,#)
Try these options, even though you say you have no access to coordinates, which is rare for graphical utilities in R, but may well be a future edit to heatmap.3. You could also use a fancy R utility called locator(1) to point and click with your mouse where you want to see your legend.
In general, the legend option is formally defined as:
legend(location, title, legend, ...)
If you have any more questions about the legend utility in R, please type in help(legend) in your R command line (in R Studio, for instance, if you use that).
To address your question on multiple legends, please consult: Plotting multiple legends
So I have a bunch of matrices that I am trying to plot as a heatmaps. I am using the heatmap.2() function in the ggplot2 packaage.
I have been trying for quite some time with it, and I am sure there is a very simple fix, but my issue is this:
How do I keep the colours consistent between heatmaps? For example, to make the values that provide the colours absolute as opposed to relative.
I have tried doing something similar to this question:
R/ggplot: Reuse color key for multiple heat maps
But I was unable to figure out the ggplot function; I kept receiving an error message stating that there were "no layers in plot".
After reading the comments on the above question, I tried using scales::rescale() and discrete_scale() but the former does not remove the problem, while the latter did not work.
I am fully aware that I might be doing something very simple wrong, and just being a bit of an idiot, but for the life of me I can't figure out where I am going wrong.
As for the data itself, I am trying to plot 10 matrices/heatmaps, each 10x10 cells (showing change over time) and the values in the cells range from 1.0 to 1.2.
As an example, this is the code I am using (once I have my 10x10 matrix).
Matrix1<-matrix(data=(runif(100,1.0,1.2)),nrow=10,ncol=10)
heatmap.2(Matrix1, Colv=NA, Rowv=NA, dendrogram="none",
trace="none", key=F, cellnote=round(Matrix1,digits=2),
notecex=1.6, notecol="black",
labRow=seq(10,100,10), labCol=seq(10,100,10),
main="Title1", xlab="Xlab1", ylab="Ylab1"
)
So any help with either figuring out how to create the scaled values for the heatmap.2() function, or how I can use the ggplot() function would be greatly appreciated!
It's important to note that heatmap.2 is not a ggplot2 function. The ggplot2 package is not necessarily compatible with all plotting types. If you look at the ?heatmap.2 help page, in the upper left corner it shows you where the function is from. heatmap.2 {gplots} means that function comes from the gplots package. These are different pacakges so they have different rules how they work.
To get the same colors across different heatmaps, you want to explicitly get the breaks= parameter. By default it splits the observed range of the data into equal chunks. But since each data set may have a different min and max, these chunks may have different start and end points. By specifying breaks, you can make them all consistent. Since your data ranges from 1 to 1.2, you can set
mybreaks <- seq(1.0, 1.2, length.out=7)
and then in your call add
heatmap.2(Matrix1, Colv=NA, Rowv=NA, dendrogram="none",
...
breaks=mybreaks,
...
)
That should make them all match up.
Maybe this will help you. With the following code multiple heatmaps are stored in a list and displayed in a grid later on. This will allow you to control the colours of each heatmap since each heatmap is created separately. So in this case I chose to use green and red for the number range in each chart.
data(mtcars)
require(ggplot2)
require(gridExtra)
myplotslist2 <- list()
var = c("mpg", "wt", "drat")
new = cbind(mtcars, "variable")
new = cbind(car = rownames(mtcars), new)
for (i in 1:length(var)){
t= paste("new[[\"variable\"]] = \"", var[[i]],"\"; a = ggplot(new, aes(variable, car)) + geom_tile(aes(fill = ", var[[i]], "),colour = \"white\") + scale_fill_gradient(low = \"red\", high = \"green\") + theme(axis.title.y=element_blank(), axis.text.y=element_blank(),legend.position=\"none\"); myplotslist2[[i]] = a")
eval(parse(text=t))
}
grid.arrange(grobs=myplotslist2, ncol=length(var))
The result looks like this:
I hope this helps.
I explain more in my blogpost. https://dwh-businessintelligence.blogspot.nl/2016/05/pca-3d-and-k-means.html
I am trying to plot several lines using the lattice package to produce a tiled figure. Here is an example (which is wrong, see bellow):
(source: ubuntuone.com)
I would like to mimic this one (in terms of the colour pattern) :
(source: ubuntuone.com)
Both plots are colouring the same variable "subset$speed1DaboveT". The first is done with xyplot the second with levelplot.
My problem is that the one with the curves is not colouring correctly, possibly because i am asking the wrong thing. I have followed this example from another question (which, importantly, is a single figure):
dfrm <- data.frame( y=c(rnorm(10),rnorm(10)),
x=1:10,
grp=rep(c("a","b"),each=10))
xyplot(y~x, group=grp, type="l", data=dfrm, col=c("red","blue"))
By doing:
keys=unique(subset$speed1DaboveT)
theseCol= colF(length(keys))
pp= xyplot( freq~patch|B+G
,data=subset
,scales=list( x=list(cex=0.5), y=list(cex=0.5,lim=c(0,1.1)) )
,strip = FALSE
,t='l'
,group=speed1DaboveT
,col=theseCol
,lwd=2
,cex=0.5
,panel = function(x, y, col, ...) {
panel.xyplot(x, y, col=col, ...)
}
)
In my case i am using 2 factors (B and G) and the example has none. This may mean that the colours given to xyplot should perhaps follow a different order? Anyone knows how to?
So, i failed to notice that the range would not be the same. Sorry for the question, things were solved once i forced the colour range of the xyplot to be the same as the levelplot, that is [0,0.16]
thanks