带有标签线的自定义轴

Posted

技术标签:

【中文标题】带有标签线的自定义轴【英文标题】:Custom axis with lines to labels 【发布时间】:2012-09-20 11:27:39 【问题描述】:

我不知道如何表达这个问题,但我正在尝试将带有线条的标签添加到基本散点图上的对应点。到目前为止,我有以下内容:

example <- data.frame(name=paste("label_",1:200,sep=""),plot=rep(FALSE,200),rank=c(1:200),score=exp(seq(6,0,length.out=200)))
example$plot[c(1:3,7,8,35,37,150:155,183)] <- TRUE

plot(x=example$score,y=example$rank,ylim=rev(range(c(1:nrow(example)))),axes=FALSE,ylab="",xlab="Score",frame.plot=FALSE)
axis(side=1,labels=TRUE)
axis(side=2,labels=example$name[which(example$plot==TRUE)],at=example$rank[which(example$plot==TRUE)],las=1,tick=FALSE)
points(x=example$score[which(example$plot==TRUE)],y=example$rank[which(example$plot==TRUE)],col="Red",cex=1.5,pch=16)

代码给出了以下情节:

这对我的目的很有效,除了标签重叠非常严重。我正在寻找一种通用方法来制作如下图:

代码位于函数中,因此它需要适用于通用数据集的任何变化。我正在查看 safe 包中 safeplot 背后的代码,但到目前为止,我无法复制他们为解决类似问题所做的工作。

我现在也尝试使用 vegan 包中的 linestack() 函数。

par(mar=c(5,10,4,2))
plot(x=example$score,y=example$rank,ylim=rev(range(c(1:nrow(example)))),axes=FALSE,ylab="",xlab="Score",frame.plot=FALSE)
axis(side=1,labels=TRUE)
points(x=example$score[which(example$plot==TRUE)],y=example$rank[which(example$plot==TRUE)],col="Red",cex=1.5,pch=16)
linestack(x=example$rank[which(example$plot==TRUE)],labels=example$name[which(example$plot==TRUE)],add=TRUE,side="left",air=1.1,at=0,hoff=2)

但是,linestack() 只是给了我以下信息:

我尝试改变所有参数,但无法将标签分开。

【问题讨论】:

您可以使用lines()text() 函数绘制这些线条和标签。 lines()text() 函数仅在绘图区域内绘制,而不在边缘绘制。 linestext 可以用par(xpd=TRUE) 画出边距。 我也试过了。我不清楚xpd=TRUE 时坐标系是如何工作的。 与绘图区域的坐标系相同。在内部区域之外绘制时我喜欢做的是首先在绘图区域中获取我需要的所有内容,然后调用par(new=TRUE, xpd=TRUE),然后调用plot(NA, NA, type='n', xlim=my.xlim, ylim=my.ylim),其中my.xlimmy.ylim 是方便的xaxis 和yaxis 范围,用于在外部绘制边距,例如,my.xlim=c(0,1) 【参考方案1】:

这里有几个问题,特别是通常您不能在绘图区域之外绘制,因为剪裁会遮盖超出限制的任何内容(即在边距中)。您还需要在该边距中留出大量空间以容纳标签和线条。

虽然这比我现在可以在 SO 上从事的工作更重要,但我建议您查看 vegan 包中的 linestack() 函数以及它在 @ 中的使用方式987654322@方法。

我最近使用 `linestack() 函数做了一些与您描述的非常相似的事情,以改进 glmnet 包中的一些绘图。如果您需要更多帮助,请回复评论,我会一起编写一个示例。

【讨论】:

感谢您的回复。我会检查 linestack() 并让你知道我是否可以让它工作。在我的实际代码中,我确实增加了边距,我只是没有费心为示例添加代码行。再次感谢! 我尝试了linestack() 函数,但无法让它工作。我用我运行的代码更新了我的问题。 当你有时间时,我真的很感激一个例子。这似乎仍然是最有效的解决方案。提前致谢。 我发现了问题。 linestack() 函数在分隔标签时使用 strheight 函数作为乘数。当我在我的情节调用中将ylim 分配给反向时,它导致strheight 变为负数 - 因此标签不会分开。该函数的作用就像一个带有负 air 值的魅力。谢谢! @PatrickT 我的编辑被拒绝了。我所做的只是重写 vegan 包中的 linestack 函数。您只需要通过在strheight 调用周围包裹abs 来修复ht &lt;- air * strheight(names(x), cex = cex) 行。【参考方案2】:

查看 TeachingDemos 包中的 spread.labs 函数和 plotrix 包中的 spread.labels 函数,了解选择标签放置位置的方法。

设置par(xpd=NA)可以让你使用text,lines,segments等函数在绘图区域外绘制。

grconvertX 函数也可能有助于找到标签和线段的水平位置。

【讨论】:

以上是关于带有标签线的自定义轴的主要内容,如果未能解决你的问题,请参考以下文章

ios 顶部带有标签栏的自定义 uitableview

将带有外键的自定义标签呈现到模板问题中

在带有多个参数的自定义模板标签的模板中使用“if”

在 WooCommerce 产品页面中显示带有标签和值的自定义字段?

Google Maps API,添加带有标签的自定义 SVG 标记

如何在目标c中创建带有标签和文本字段的自定义单元格