Vary colors of axis labels in R based on another variable

血红的双手。 提交于 2019-12-17 18:38:33

问题


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:

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

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


回答1:


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:




回答2:


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
} 



回答3:


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)

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)) 



回答4:


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)


来源:https://stackoverflow.com/questions/18839731/vary-colors-of-axis-labels-in-r-based-on-another-variable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!