R中的智能点标签放置


102

1)是否有任何R库/函数可以在R图中实现INTELLIGENT标签的放置?我尝试了一些,但它们都是有问题的-许多标签彼此重叠或与其他点(或图中的其他对象重叠),但我发现这很难处理。

2)如果没有,有什么方法可以通过特定问题点的标签放置来舒适地帮助算法?需要最舒适有效的解决方案。

您可以使用我的可复制示例来测试和测试其他可能性,并查看是否能够获得比我更好的结果:

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")

# basic plot
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

为了贴标签,我尝试了这些可能性,没有人真的很不错:

1)这很可怕:

text(x, y, labels = ShortSci, cex= 0.7, offset = 10)

2)如果您不想为所有点都放置标签,而只是为离群值放置标签,那么这是一个好方法,但是仍然经常将标签放置错误:

identify(x, y, labels = ShortSci, cex = 0.7)

3)这个看上去很不合理,但是存在标签太靠近点的问题;我不得不在它们之间填充空格,但这并没有太大帮助:

require(maptools)
pointLabel(x, y, labels = paste("  ", ShortSci, "  ", sep=""), cex=0.7)

4)

require(plotrix)
thigmophobe.labels(x, y, labels = ShortSci, cex=0.7, offset=0.5)

5)

require(calibrate)
textxy(x, y, labs=ShortSci, cx=0.7)

先感谢您!

编辑:待办事项:试试labcurve {Hmisc}


2
不幸的是,R问题的答案似乎在StackOverflow和CrossValidated之间平均分配。在这种情况下,问题是4天前那边的一个重复问题。
Ed Staub

3
我遇到了一个类似的问题,并编写了一个使用力场模拟来调整对象位置的基本软件包。尽管可以进行很多改进,包括与ggplot集成等,但似乎可以完成任务。下面说明了该功能。如果有人遇到问题并寻找答案,希望对您有所帮助:install.packages("FField") library(FField) FFieldPtRepDemo()
gregk 2013年

我可以请您尝试格雷格雷吗?
卡米尔Slowikowski

亲爱的@Joran,请发表您的评论“ 6)对于ggplot2图,有很多人喜欢的新选项ggrepel。” 在评论或答案中。在这里,我只列出了我尝试过的选项列表,但并不令人满意。如果这是行之有效的话,那应该是一个答案。
TMS

Answers:


49

首先,这是我解决此问题的结果:

在此处输入图片说明

我仅用了几分钟就在Preview(OS X中非常基本的PDF /图像查看器)中手动完成了此操作。(编辑:工作流程正是您所期望的:我从R将图另存为PDF,在“预览”中将其打开,并使用所需标签(9pt Helvetica)创建了文本框,然后用鼠标将其拖动直到它们看上去好。然后我导出到PNG以上传到SO。)

现在,在您屈服于强烈反对将其投弃票并就此过程自动化的意义发表leave昧评论之前,请听我说!

寻找算法解决方案完全可以,而且(IMHO)真的很有趣。但是,对我来说,标记点的情况大致分为三类:

  1. 你只有很少的一点,没有一点紧密地靠在一起。在这种情况下,您在问题中列出的解决方案之一可能会进行相当小的调整。
  2. 您只有很少的点,其中一些点对于典型的算法解决方案来说过于紧密,无法给出良好的结果。在这种情况下,由于您只有很少的点,因此手动标记它们(使用图像编辑器或对进行微调text)并不需要那么多精力。
  3. 您有相当多的分数。在这种情况下,您真的不应该为它们加上标签,因为很难直观地处理大量标签。

:爬到肥皂盒上:

由于像我们这样的人都喜欢自动化,所以我认为我们经常陷入这样的陷阱:制作好的统计图形的几乎每个方面都应该自动化。我恭敬地(谦卑!)不同意。

没有完美的通用统计绘图环境可以自动创建您脑海中的图像。R,ggplot2,lattice之类的东西可以完成大部分工作;但是稍微多一点的调整,在此处添加一条线,在此处调整边距,可能更适合于其他工具。

:从肥皂盒爬下来:

我还要指出,我认为我们所有人都可以拿出<10-15点的散点图,即使是手工也几乎不可能清楚地标记出来,而这很可能会破坏有人想出的任何自动解决方案。

最后,我想重申一下,我知道这不是您要找的答案。我并不是说算法尝试是无用的或愚蠢的。我对这个问题投了赞成票,并将愉快地投票给有趣的算法解决方案!

我发布此答案的原因是,我认为这个问题应该是未来重复项的规范“ R中的点标记”问题,而且我认为涉及手工标记的解决方案应该摆在桌面上。


10
另一种手动方式是将图另存为SVG并使用Inkscape对其进行编辑,然后从中生成PDF。
Spacedman 2011年

嗨,乔兰,谢谢您的回答。好的,我接受此解决方案,尽管我认为计算机应该首先做到这一点,然后再请求人工干预。在这里,我正在寻找最舒适,最快捷的解决方案。您能一步一步地描述您如何制作情节吗?您在R中生成了什么,如何在预览中导出,移动标签等?
TMS

1
@TomasT。哦,我明白了。在那种情况下,我被“欺骗”了。我使用上面的一种方法生成了一个带有标签的pdf,而没有使用的一种方法生成了pdf,并使用了带有标签的一个pdf作为指导。
joran 2011年

1
+1这是一个很好的答案。关于为什么会出现在meta-CV上的一些解释:请参阅此处的评论。
whuber 2011年

1
手动移动一小组标签似乎很明智,但是您最好先自动创建一个标签,然后再移动它们。这样,您就可以节省很多工作,还可以减少

42

ggrepel应用于ggplot2散点图时看起来很有希望。

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")


df <- data.frame(x = x, y = y, z = ShortSci)
library(ggplot2)
library(ggrepel)

ggplot(data = df, aes(x = x, y = y)) + theme_bw() + 

    geom_text_repel(aes(label = z), 
       box.padding = unit(0.45, "lines")) +

    geom_point(colour = "green", size = 3)

在此处输入图片说明


10

您是否尝试过directlabels软件包?

而且,顺便说一句,pos和offset参数可以采用矢量,以使您可以在几幅图中有合理数量的点时将它们放置在正确的位置。


directlabel软件包可以与法线plot()图一起使用吗?我尝试失败,所以...谢谢!PS:@SpacedMan&Ben,我整理了有关R update的评论,因为它们并不是那么有趣-您可以执行相同操作。
TMS

6

我找到了解决方案!不幸的是,这不是终极的和理想的,但它现在对我来说是最合适的。这是一半算法,一半手动,因此与joran绘制的纯手动解决方案相比节省了时间。

我忽略帮助中非常重要的部分?identify

如果在此处指定pos,则用于放置标签的算法与文本所使用的算法相同,不同之处在于,指针相对于已识别点的位置确定了pos的身份。

因此,如果您使用identify()我在问题中所写的解决方案,那么可以通过不直接单击该点,而是相对地按所需方向单击该点旁边来影响标签的位置!!!效果很好!

缺点是只有4个位置(上,左,下,右),但我更欣赏其他四个位置(左上,右上,左下,右下)...所以我如joran所建议的那样,用它来标记那些不会困扰我的点以及我直接在Powerpoint演示文稿中直接标记的其余点:

PS:我还没有尝试过directlabels格/ ggplot解决方案,我仍然更喜欢使用基本的图库。


4

我建议您看一看wordcloud包装。我知道这个软件包不仅仅着眼于重点,还着眼于标签本身,而且样式似乎很固定。但是,我从使用它获得的结果还是非常惊人的。还要注意,所涉及的软件包版本是在您提出问题时发布的,因此它仍然是非常新的。

http://blog.fellstat.com/?cat=11


3

我已经addTextLabels()在包中编写了一个R函数plotteR。可以使用以下代码将软件包直接安装到R库中:

install.packages("devtools")
library("devtools")
install_github("JosephCrispell/basicPlotteR")

对于提供的示例,我使用以下代码生成了下面链接的示例图。

# Load the plotteR library
library(plotteR)

# Create vectors storing the X and Y coordinates
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
      0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
      0.9717, 0.9357)

# Store the labels to be plotted in a vector
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
             "SaxRub", "TurMer", "TurPil", "TurPhi")

# Plot the X and Y coordinates without labels
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

# Add non-overlapping text labels
addTextLabels(x, y, ShortSci, cex=0.9, col.background=rgb(0,0,0, 0.75), 
              col.label="white")

它通过自动从精细的点网格中选择替代位置来工作。如果网格上最接近的点不与任何绘制的点或标签重叠,则将首先访问并选择这些点。如果有兴趣,请看一下源代码

示例图


2

不是答案,但是评论太久。在joran的后处理和已经提出的更复杂的算法之间的某个简单情况下,可以在简单情况下工作的方法是对数据框进行in-place简单转换。

ggplot2之所以说明这一点,是因为我比基本R图更熟悉该语法。

df <- data.frame(x = x, y = y, z = ShortSci)
library("ggplot2")
ggplot(data = df, aes(x = x, y = y, label = z)) + theme_bw() + 
    geom_point(shape = 1, colour = "green", size = 5) + 
    geom_text(data = within(df, c(y <- y+.01, x <- x-.01)), hjust = 0, vjust = 0)

如您所见,在这种情况下,结果并不理想,但对于某些目的来说可能已经足够了。而且这很轻松,通常像这样就足够了within(df, y <- y+.01)

在此处输入图片说明


2
我通常不通过调整外观df来修改within用法:geom_text(aes(x = x - .01, y = y + .01), hjust = 0, vjust = 0)看上去更干净。
格里戈尔·托马斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.