为啥当 hjust 和 vjust 是字符串时 geom_text() 会抛出强制错误?

Posted

技术标签:

【中文标题】为啥当 hjust 和 vjust 是字符串时 geom_text() 会抛出强制错误?【英文标题】:Why does geom_text() throw coercion errors when hjust and vjust are strings?为什么当 hjust 和 vjust 是字符串时 geom_text() 会抛出强制错误? 【发布时间】:2011-07-01 15:58:17 【问题描述】:

我注意到ggplot2geom_text() geom 中有一个意外行为。如果属性hjustvjust 被指定为字符串,R 会返回强制错误,尽管绘图看起来不错。问题出现在我正在开发的ggplot2-based package 中。为简单起见,我创建了仍然会产生错误的精简示例。

首先,我用qplot()试了一下

##qplot version
library(ggplot2)
p <- qplot(cty, hwy, 
           label = drv, 
           hjust = "right", 
           geom  = "text", 
           data  = mpg
)

print(p)

我得到了这个错误:

Warning message:
In validDetails.text(x) : NAs introduced by coercion

然后我用ggplot()试了一下:

##ggplot version
library(ggplot2)
p <- ggplot(
          aes(x   = cty,
              y   = hwy
          ), data = mpg
)

p <- p + geom_text(
           aes(label = drv),
           hjust     = "right"
)

print(p)

得到了相同的情节和相同的错误:

Warning message:
In validDetails.text(x) : NAs introduced by coercion

然后我尝试同时设置 hjust 和 vjust:

library(ggplot2)
p <- ggplot(
          aes(x   = cty,
              y   = hwy
          ), data = mpg
)

p <- p + geom_text(
           aes(label = drv),
           hjust     = "right",
           vjust     = "top"
)

print(p)

使用字符串设置两个参数时,R 返回两个强制错误:

Warning messages:
1: In validDetails.text(x) : NAs introduced by coercion
2: In validDetails.text(x) : NAs introduced by coercion

但是,当参数是数字时,R 不会返回强制错误:

## Using numbers instead of strings
library(ggplot2)
p <- ggplot(
          aes(x   = cty,
              y   = hwy
          ), data = mpg
)

p <- p + geom_text(
           aes(label = drv),
           hjust     = 0,
           vjust     = 0,
           data      = mpg
)

print(p)

我不太确定为什么会发生这种情况,或者它是否很重要,但我没想到。

ggplot2 文档不同意

Hadley's book(第 196 页)说 hjustvjust 可以接受字符串参数:

字符串(或图例)的对齐方式定义了在 放置在给定位置的字符串。有两个值 用于水平和垂直对齐。这些值可以是:

一个字符串:“left”、“right”、“centre”、“center”、“bottom”和“top”。 一个介于 0 和 1 之间的数字,表示字符串中的位置(从左下角开始)。

但是 0.8.9 版中 geom_text() 的 man 文件说 hjust 和 vjust 是数字,尽管它没有说它们可以 只有是数字:

美学

geom_text 可以使用以下美学。美学通过 aes 函数映射到数据中的变量:geom_text(aes(x = var))

x:x 位置(必填) y:y 位置(必填) label:文本标签(必填) 颜色:边框颜色 尺寸:尺寸 角度:角度 hjust:水平对齐,介于 0 和 1 之间 vjust:垂直对齐,介于 0 和 1 之间 alpha:透明度

【问题讨论】:

非常特别的是,ggplot2 本书第 196 页并没有说 hust 和 vjust 可以具有这些值......它只是说(粗略地)“理由”可以是......请参阅下面的完整“答案”。 【参考方案1】:

hjustvjust 应该是数字,查看手册(?geom_text):

hjust':水平对齐方式,介于 0 和 1 之间 ‘vjust’:垂直对齐,介于 0 和 1 之间

【讨论】:

我同意手册说 hjust 和 vjust 应该是数字。我已经编辑了这个问题,以反映哈德利的书似乎很清楚地指出它们也可以是字符串。我不清楚哪些文件取代了哪些文件。 代码取代所有文档;文件的谎言。 :)【参考方案2】:

所以,我不太了解 WHAT CODE 定义或使用 hjust/vjust,但是使用 TextMate 的“在项目中查找”(在 ggplot2/R/ 目录中)进行 hjust,我看不到任何看起来就像它们是 hjust 的定义或实现......只是它被列为有效 aes 并被传递的地方。

这让我想去阅读网格......

http://stat.ethz.ch/R-manual/R-patched/library/grid/html/grid.text.html

这让我想了解更多关于 grid.text 是如何定义的

R> grid.text

function (label, x = unit(0.5, "npc"), y = unit(0.5, "npc"), 
    just = "centre", hjust = NULL, vjust = NULL, rot = 0, check.overlap = FALSE, 
    default.units = "npc", name = NULL, gp = gpar(), draw = TRUE, 
    vp = NULL) 

    tg <- textGrob(label = label, x = x, y = y, just = just, 
        hjust = hjust, vjust = vjust, rot = rot, check.overlap = check.overlap, 
        default.units = default.units, name = name, gp = gp, 
        vp = vp)
    if (draw) 
        grid.draw(tg)
    invisible(tg)

<environment: namespace:grid>

所以,它是一个 textGrob,而 just、hjust 和 vjust 只是简单地被传递给它...关闭到 textGrob

R> textGrob
function (label, x = unit(0.5, "npc"), y = unit(0.5, "npc"), 
    just = "centre", hjust = NULL, vjust = NULL, rot = 0, check.overlap = FALSE, 
    default.units = "npc", name = NULL, gp = gpar(), vp = NULL) 

    if (!is.unit(x)) 
        x <- unit(x, default.units)
    if (!is.unit(y)) 
        y <- unit(y, default.units)
    grob(label = label, x = x, y = y, just = just, hjust = hjust, 
        vjust = vjust, rot = rot, check.overlap = check.overlap, 
        name = name, gp = gp, vp = vp, cl = "text")

<environment: namespace:grid>

所以,这是一个 grob............ 去 grob......

R> grob
function (..., name = NULL, gp = NULL, vp = NULL, cl = NULL) 

    g <- list(..., name = name, gp = gp, vp = vp)
    if (!is.null(cl) && !is.character(cl)) 
        stop("Invalid 'grob' class")
    class(g) <- c(cl, "grob", "gDesc")
    validGrob(g)

<environment: namespace:grid>

那里没什么帮助,所以我谷歌了

R grid hjust vjust

在覆盖 Google 对我的搜索的自动更正后,我发现

http://rwiki.sciviews.org/doku.php?id=tips:graphics-grid:hvjust

回顾哈德利的书,我注意到第 196 页的参考实际上并没有提及 hjust 或 vjust... 只是证明。

阅读文档

R> ?textGrob

我明白了

just     The justification of the text relative to its (x, y) location. If there are two values, the first value specifies horizontal justification and the second value specifies vertical justification. Possible string values are: "left", "right", "centre", "center", "bottom", and "top". For numeric values, 0 means left alignment and 1 means right alignment.
hjust    A numeric vector specifying horizontal justification. If specified, overrides the just setting.
vjust    A numeric vector specifying vertical justification. If specified, overrides the just setting.

所以,这是我的想法。

just 参数可以是字符串或数字 hjust 和 vjust 只是数字,可以覆盖 just 如果您尝试为它们使用字符串,它可能“有效”,但会引发警告

所以,让我们看看 grid.text 演示代码,特别是 draw.text 函数,他们在其中使用并且似乎成功地使用了字符串值:

grid.newpage()
x <- stats::runif(20)
y <- stats::runif(20)
rot <- stats::runif(20, 0, 360)
grid.text("SOMETHING NICE AND BIG", x=x, y=y, rot=rot,
          gp=gpar(fontsize=20, col="grey"))
grid.text("SOMETHING NICE AND BIG", x=x, y=y, rot=rot,
          gp=gpar(fontsize=20), check=TRUE)
grid.newpage()

draw.text <- function(just, i, j) 
  grid.text("ABCD", x=x[j], y=y[i], just=just)
  grid.text(deparse(substitute(just)), x=x[j], y=y[i] + unit(2, "lines"),
            gp=gpar(col="grey", fontsize=8))


x <- unit(1:4/5, "npc")
y <- unit(1:4/5, "npc")
grid.grill(h=y, v=x, gp=gpar(col="grey"))
draw.text(c("bottom"), 1, 1)
draw.text(c("left", "bottom"), 2, 1)
draw.text(c("right", "bottom"), 3, 1)
draw.text(c("centre", "bottom"), 4, 1)
draw.text(c("centre"), 1, 2)
draw.text(c("left", "centre"), 2, 2)
draw.text(c("right", "centre"), 3, 2)
draw.text(c("centre", "centre"), 4, 2)
draw.text(c("top"), 1, 3)
draw.text(c("left", "top"), 2, 3)
draw.text(c("right", "top"), 3, 3)
draw.text(c("centre", "top"), 4, 3)
draw.text(c(), 1, 4)
draw.text(c("left"), 2, 4)
draw.text(c("right"), 3, 4)
draw.text(c("centre"), 4, 4)

现在请注意,如果我将 draw.text 更改为使用 hjust 和 vjust AS STRINGS

grid.newpage()
x <- stats::runif(20)
y <- stats::runif(20)
rot <- stats::runif(20, 0, 360)
grid.text("SOMETHING NICE AND BIG", x=x, y=y, rot=rot,
          gp=gpar(fontsize=20, col="grey"))
grid.text("SOMETHING NICE AND BIG", x=x, y=y, rot=rot,
          gp=gpar(fontsize=20), check=TRUE)
grid.newpage()

draw.text <- function(just, i, j) 
  grid.text("ABCD", x=x[j], y=y[i], hjust=just[1], vjust=just[2])
  grid.text(deparse(substitute(just)), x=x[j], y=y[i] + unit(2, "lines"),
            gp=gpar(col="grey", fontsize=8))
  

x <- unit(1:4/5, "npc")
y <- unit(1:4/5, "npc")
grid.grill(h=y, v=x, gp=gpar(col="grey"))
draw.text(c("bottom"), 1, 1)
draw.text(c("left", "bottom"), 2, 1)
draw.text(c("right", "bottom"), 3, 1)
draw.text(c("centre", "bottom"), 4, 1)
draw.text(c("centre"), 1, 2)
draw.text(c("left", "centre"), 2, 2)
draw.text(c("right", "centre"), 3, 2)
draw.text(c("centre", "centre"), 4, 2)
draw.text(c("top"), 1, 3)
draw.text(c("left", "top"), 2, 3)
draw.text(c("right", "top"), 3, 3)
draw.text(c("centre", "top"), 4, 3)
draw.text(c(), 1, 4)
draw.text(c("left"), 2, 4)
draw.text(c("right"), 3, 4)
draw.text(c("centre"), 4, 4)

长话短说:我认为当你使用 hjust 或 vjust 作为字符串时,你违反了文档(它的值应该是数字 0

【讨论】:

在查看 textGrob 的文档时,我想我真正的问题是:为什么 ggplot2 的 theme_text() 不能只接受并传递 just 参数,以便用户可以指定对齐向量,例如just=c("bottom", "centre")? 可以...它只是不能。也许这暗示了对 ggplot2 的拉取请求?

以上是关于为啥当 hjust 和 vjust 是字符串时 geom_text() 会抛出强制错误?的主要内容,如果未能解决你的问题,请参考以下文章

text ggplot2 vjust hjust标签

R语言ggplot2可视化使用vjust和hjust参数对齐图像中的文本注释信息(左对齐右对齐居中)实战

是否有功能在R中执行类似于hjust / vjust或position_dodge的操作?

【R】热图绘制

当角度在 45 到 90 之间时,如何更正 x 轴文本的位置?

热图一