我发现一个问题时,绘制十六进制图形使用ggplot2.当我使用geom_text向图表添加文本时,它需要很长的时间!

我做了minimal, self-contained, reproducible example,你可以很容易地找到这个问题.

library(ggplot2)
d1 <- ggplot(diamonds, aes(carat, price)) + 
  geom_hex()
d2 <- d1+ 
  geom_text(x=3,y=5000,
            label="y = 0.0243x + 0.298\nR^2 = 0.648, p < 2.2e-16")

system.time({
  print(d1)
})
#   user  system elapsed 
#   0.11    0.01    0.13

system.time({
  print(d2)
})
#   user  system elapsed 
#   0.75    2.84    3.61 

对于非常少量的数据,geom_text使运行时间延长了27倍以上.对于我的真实代码,它将运行时从3.65s to 162.30s增加(more than 44 times,请注意,这只是当运行完成时,它需要更多的时间来显示在窗格中).

我不知道是什么原因造成的,但我觉得在图形中添加文本应该是一个更基本的图形设置,所以我真诚地希望这个问题可以得到解决.此外,由于超长的运行时间,它经常导致我想停止运行时R崩溃(这让我非常沮丧).我也很好奇是否有更合适的方法来结束运行过程,并保持R程序正常运行.

推荐答案

问题

ggplot2期望美学与数据长度相同.geom_text()把你的字符串重复到每一行数据.我们可以看看ggplot2ggplot2::ggplot_build()一起使用的数据:

dat  <- ggplot_build(d2)
lapply(dat$data, head,2)
# [[1]]
#      fill         x          y     width   height      density     ndensity count       ncount PANEL group colour linewidth linetype alpha
# 1 #132B43 0.3206657  -0.000001 0.1603333 616.5667 1.853912e-05 0.0001721467     1 0.0001721467     1    -1     NA       0.5        1    NA
# 2 #53ABEE 0.2404990 533.962395 0.1603333 616.5667 1.030033e-01 0.9564468928  5556 0.9564468928     1    -1     NA       0.5        1    NA

# [[2]]
#   PANEL group colour size angle hjust vjust alpha family fontface lineheight x    y                                         label
# 1     1    -1  black 3.88     0   0.5   0.5    NA               1        1.2 3 5000 y = 0.0243x + 0.298\nR^2 = 0.648, p < 2.2e-16
# 2     1    -1  black 3.88     0   0.5   0.5    NA               1        1.2 3 5000 y = 0.0243x + 0.298\nR^2 = 0.648, p < 2.2e-16

第一个数据帧包含每个六边形的坐标.第二个包含相同的文本,重复了53,940次(行数为diamonds).

一种方法是reproduce both plots as svg strings.你会看到d2字符串包含以下两行重复了nrow(diamonds)次:

<text x='404.35' y='510.41' text-anchor='middle' style='font-size: 11.04px; font-family: "Arimo";' textLength='144.40px' lengthAdjust='spacingAndGlyphs'>R^2 = 0.648, p &lt; 2.2e-16</text>
<text x='404.35' y='494.51' text-anchor='middle' style='font-size: 11.04px; font-family: "Arimo";' textLength='115.77px' lengthAdjust='spacingAndGlyphs'>y = 0.0243x + 0.298</text>

当你看图时,你看不到额外的107,880行,因为每次文本都是在自己上面绘制的.然而,渲染将需要更长的时间.如果以描述如何渲染图的格式保存图,例如svg,它会大得多(20mb与85kb相比).但是,如果你把它保存为像素的表示,例如png,你将不会观察到任何差异.

溶液

您不想将文本映射到您的数据,因此对于这种情况,您应该使用ggplot2::annotate().正如doctor 所说,

几何体的属性不是从数据帧的变量映射的,而是作为向量传递.这对于添加小注释(如文本标签)非常有用.

d3 <- d1 + annotate(
    "text", 
    x = 3, 
    y = 5000, 
    label = "y = 0.0243x + 0.298\nR^2 = 0.648, p < 2.2e-16"
)

这只生成一次文本,所以不应该引起这个问题:

system.time(print(d1))
#   user  system elapsed
#   0.11    0.01    0.13

system.time(print(d3))
#    user  system elapsed 
#   0.141   0.000   0.141 

类似地,与20mb的d2.svg不同,d3保存到svg时的大小为85kb,与d1相同.

R相关问答推荐

根据shiny 应用程序中的数字输入更改图标 colored颜色

将复杂的组合列表转换为数据框架

pickerInput用于显示一条或多条geom_hline,这些线在图中具有不同 colored颜色

如何动态更新selectizeInput?

如何改变x轴比例的列在面

根据文本字符串中的值粘贴新列

如果可能,将数字列转换为整数,否则保留为数字

我正在努力用R计算数据集中的中值逐步距离

计算两列中满足特定条件连续行之间的平均值

有没有一种方法可以同时对rhandsontable进行排序和从rhandsontable中删除?

跨列查找多个时间报告

汇总数据帧中的复制列,保持行的唯一性

按组计算列中1出现的间隔年数

'使用`purrr::pwalk`从嵌套的嵌套框架中的列表列保存ggplots时出现未使用的参数错误

如果条件匹配,则使用Mariate粘贴列名

如何显示准确的p值而不是<;0.001*?

如何在刻面和翻转堆叠条形图中对齐geom_text()

如何用不同长度的向量填充列表?

从data.table列表中提取特定组值,并在R中作为向量返回

Data.table条件合并