Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vary colors of axis labels in R based on another variable

Tags:

plot

r

ggplot2

I usually use ggplot2, but in this case I am using the regular image() function to plot a heatmap of a large data set. I can label all the labels as red, but I want to label the y-axis with text of different colors based on a vector of color definitions that I generate:

grid = structure(c(1:12),.Dim = c(4,3))
labs = c("A","B","C")
image(1:4,1:3,grid,axes=FALSE, xlab="", ylab = "")
#This works but isn't the colors I want
axis(2,at=1:length(labs),labels=labs,las=2, adj=1,cex.axis=0.6,col.axis="red")

That generates the following image:

Example plot

I would like labels A and C to be black and B to be red. This is what I tried, but it gives a "wrong length" error...

axiscolors = c("black","red","black")
axis(2,at=1:length(labs),labels=labs,las=2, adj=1, cex.axis=0.6, col.axis=axiscolors)

This is the effect I am after with some "real" data...

actual heatmap

EDIT:

As a back-up, if this is possible in ggplot2, I might be willing to re-factor my code. There are a couple other applications I would use this for as well.

I figured out a way to plot a layer of red symbols over the top of the old labels, but would prefer a native method with the color vector, if possible...

sublabs = c("B")
axis(2,at=match(sublabs,labs),labels=sublabs,las=2, adj=1, cex.axis=0.6, col.axis="red")

Another way would be to use text() if I could put the labels outside the plot space...

text(c(1,1,1),c(1,2,3),labs,col=c("black","red","black"))

UPDATE: See below for a solution that works with ggplot2...

like image 893
beroe Avatar asked Sep 17 '13 01:09

beroe


People also ask

How do I customize axis in R?

You can create custom axes using the axis( ) function. axis(side, at=, labels=, pos=, lty=, col=, las=, tck=, ...) the coordinate at which the axis line is to be drawn. If you are going to create a custom axis, you should suppress the axis automatically generated by your high level plotting function.

How do I assign axis labels in R?

To set labels for X and Y axes in R plot, call plot() function and along with the data to be plot, pass required string values for the X and Y axes labels to the “xlab” and “ylab” parameters respectively. By default X-axis label is set to “x”, and Y-axis label is set to “y”.

How do you change the Y axis labels in R?

Changing axis labels To alter the labels on the axis, add the code +labs(y= "y axis name", x = "x axis name") to your line of basic ggplot code. Note: You can also use +labs(title = "Title") which is equivalent to ggtitle .


4 Answers

If you ignore the vectorised possibilities like text and mtext, you can get there by repeatedly calling axis. The overhead timewise will be very minimal and it will allow all the axis calculations to occur as they normally do. E.g.:

# original code
grid = structure(c(1:12),.Dim = c(4,3))
labs = c("A","B","C")
image(1:4,1:3,grid,axes=FALSE, xlab="", ylab = "")
axiscolors = c("black","red","black")

# new code    
Map(axis, side=2, at=1:3, col.axis=axiscolors, labels=labs, lwd=0, las=1)
axis(2,at=1:3,labels=FALSE)

Resulting in:

enter image description here

like image 147
thelatemail Avatar answered Oct 19 '22 13:10

thelatemail


Accepting @thelatemail's answer as the most flexible, but it also turns out to be pretty simple using text() if you add xpd = TRUE to allow plotting outside the frame. Using mtext() can also work, but it doesn't allow you to rotate labels.

grid = structure(c(1:20),.Dim = c(4,5))
labs = c("A","B","C","D","E")
redlabs = c("B","D")
colorlist = c("black","red")
# one of many ways to generate the color labels
axiscolor = colorlist[labs %in% redlabs +1 ]

image(1:4,1:5,grid,axes=FALSE, xlab="", ylab = "")
axis(2,at=1:length(labs),labels=FALSE)

# This would work for sideways labels
# mtext(text=labs, side=2,at=1:length(labs),col=axiscolor,adj=.5)
text(labels=labs, col=axiscolor, x=rep(.45,length(labs)), y=1:length(labs), srt = 0, pos = 2, xpd = TRUE)

Solution using text()

UPDATE for ggplot2: You can use theme() and element_text to set the colors and other parameters. Something like this...

 p + theme(axis.text.y = element_text(color=axiscolor)) 
like image 35
beroe Avatar answered Oct 19 '22 11:10

beroe


You could specify a vector with the colors you want to apply to the labels and then use a loop to get the labels colored with axis(). In the following example, I use a different color for each level of a dot chart.

DF <- data.frame(habitat=c("Hab 1","Hab 2","Hab 3","Hab 4","Hab 5"), mean=c(0.53,0.28,0.30,0.35,0.39), color=colors()[c(24,257,26,504,652)])
> DF
habitat mean      color
1   Hab 1 0.53      black
2   Hab 2 0.28     green3
3   Hab 3 0.30       blue
4   Hab 4 0.35 orangered1
5   Hab 5 0.39     yellow

par(mar=c(7, 5, 4, 3))
dotchart(DF[,2], xlim=c(0.2,0.6), col=as.character(DF$color), pch=16, lcolor="white", xlab=colnames(DF[2])) # Plot the points 
for (j in 1:5){
axis(side=2, at=j, col.axis=as.character(DF$color)[j], labels=DF$habitat[j], las=1) # Add habitat as labels, each with corresponding color, on the left margin
} 
like image 44
Esti Avatar answered Oct 19 '22 12:10

Esti


I like very much thelatemail's approach, and can only add a small refinement since the fixed "at" positions (as in the example above with at = 1:3) didn't work well for me. In my case, I needed to generate a barplot and provided my own values for space and width parameters. In the end what I used looks like (example with random data in which I wanted the bars and labels for positive (non-negative, to be more precise) data values to be green and red otherwise. For this example I also use the letters function to provide labels and rotate the labels using las = 2):

x <- rnorm(26)
color <- rep("green", length(x))
color[x < 0] <- "red"

par(mar=c(6,4.1,4.1,2.1))
barplot(x, las = 2, ylim = c(min(x)-0.5, max(x)+0.5), col = color, space = 0.5, width = 2)    
Map(function(x,y,z) 
axis(1,at=x,col.axis=y,labels=z,lwd=0,las=2),
seq(from = 2, by = 3, length.out = length(x)),
color,
letters
)
axis(1,at=seq(from = 2, by = 3, length.out = length(x)),labels=FALSE)
like image 28
Valeri Voev Avatar answered Oct 19 '22 11:10

Valeri Voev