在R中基于另一个变量改变坐标轴标签的颜色

15

我通常使用ggplot2,但在这种情况下,我正在使用常规的image()函数绘制大数据集的热图。我可以将所有标签都标记为红色,但我想根据我生成的颜色定义向量,使用不同颜色的文本标记y轴:

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

这将生成以下图像:

示例图

我希望标签A和C为黑色,B为红色。这是我尝试的方法,但它会出现“错误长度”的错误...

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

我希望得到一些“真实”的数据后,能够获得这种效果...

实际热图

编辑:

如果在ggplot2中可以实现这个效果,我可能会重新编写我的代码。我还有另外几个应用也需要使用这个效果。

我找到了一种方法,在旧标签上绘制了一层红色符号,但如果可能的话,我更喜欢使用颜色向量的本机方法...

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

如果我可以将标签放在绘图空间之外,另一种方法是使用text()

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

更新:请参考下面的解决方案,该方案适用于ggplot2...


我认为你不会找到所谓的“本地方法”。在R语言作者中,存在一种相当强烈的文化抵制力量,反对某些人所谓的“图表垃圾”。 - IRTFM
1
有趣。我是一个死忠的Tufte-an,但一个人的“图表垃圾”对另一个人来说可能是信息。(在非玩具示例中,我在y轴上有91个值,并标记了16个新插入的行以突出它们的位置。) - beroe
我查看了暴露给普通用户的代码,并没有发现在graphics::axis中可以被黑客攻击的任何东西。我想知道是否有可能通过网格图形来实现。我看到lattice::axis.default有一个版本,似乎“do.labels”部分很有前途。您可能还需要修改lattice::panel.axis - IRTFM
1
使用?mtext而不是?text是正确的方法。 - thelatemail
也许你可以使用 layout 创建独立的轴标签,并将它们放置在没有轴标签的原始图表附近。但这似乎比在旧符号上绘制一层新符号更费力。也许你可以使用 outerinset 和/或 mar 将你的 text 语句定位到绘图区域之外。 - Mark Miller
4个回答

14

如果您忽略像textmtext这样的向量化可能性,可以通过反复调用axis来实现。从时间上看,开销非常小,这将允许所有axis计算按照正常方式进行。例如:

如果你不考虑向量化的方法,如textmtext,就可以通过反复调用axis来达成目的。时间开销将非常小,并且它将允许所有axis计算按照通常方式进行。例如:

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

导致:

输入图像描述


谢谢。我喜欢这个解决方案,因为它似乎很好地扩展,并且使用自然的“axis()”命令而不是调整“text”的位置。 - beroe
刚刚尝试了一下使用mtext,效果也很棒! - undefined

5

接受 @thelatemail 的答案是最灵活的,但如果您添加 xpd = TRUE 以允许在框外绘制,则使用 text() 也非常简单。使用 mtext() 也可以工作,但它不允许您 旋转标签

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)

使用text()的解决方案

更新ggplot2:您可以使用theme()element_text设置颜色和其他参数。类似于以下内容...

 p + theme(axis.text.y = element_text(color=axiscolor)) 

3

您可以指定一个颜色向量来应用于标签,然后使用循环将带有已经着色的轴标签。在下面的示例中,我为点图的每个级别使用了不同的颜色。

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
} 

可能可行。我只是希望有一种以向量方式而不是循环方式来执行它的方法:axis(side=2, at=as.numeric(DF$habitat), col.axis=as.character(DF$color), labels=DF$habitat, las=1) - beroe

2

我非常喜欢thelatemail的方法,只能进行一些小的完善,因为固定的“at”位置(如上面的示例中的at = 1:3)对我来说效果不好。在我的情况下,我需要生成一个条形图并提供自己的空间和宽度参数值。最终我使用的看起来像是这样(在随机数据的示例中,我希望正(非负数,更加精确)数据值的条和标签为绿色,否则为红色。对于这个示例,我还使用了letters函数提供标签,并使用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)

只是提醒一下,你可以将每个条形图的中点保存为返回值,例如:bp <- barplot(x, las = 2, ylim = c(min(x)-0.5, max(x)+0.5), col = color, space = 0.5, width = 2),这样就不需要手动指定点的序列了。 - thelatemail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接