【问题标题】:ggplot aes_string doesn't work with spacesggplot aes_string 不适用于空格
【发布时间】:2018-08-02 16:47:01
【问题描述】:

不起作用:

mydat <- data.frame(`Col 1`=1:5, `Col 2`=1:5, check.names=F)
xcol <- "Col 1"
ycol <- "Col 2"
ggplot(data=mydat, aes_string(x=xcol, y=ycol)) + geom_point()

作品:

mydat <- data.frame(`A`=1:5, `B`=1:5)
xcol <- "A"
ycol <- "B"
ggplot(data=mydat, aes_string(x=xcol, y=ycol)) + geom_point()

有效。

mydat <- data.frame(`Col 1`=1:5, `Col 2`=1:5, check.names=F)
ggplot(data=mydat, aes(x=`Col 1`, y=`Col 2`)) + geom_point()

有什么问题?

【问题讨论】:

  • aes_string 的文档表明 1. 奇怪命名的列并不总是能正常工作(参见倒数第二组示例),以及 2. aes_stringaes_ 正在被弃用赞成 tidyeval
  • @camille 谢谢,你有解释 tidyeval 的链接吗?
  • 当然,这是一个:colinfay.me/tidyeval-1
  • 另外,看到this post 的答案很有趣,因为有一些是在 tidyeval 在 ggplot 中实现之前,还有一些是在实现后

标签: r ggplot2


【解决方案1】:

更新:请注意,在最新版本的ggplot2 中,不鼓励使用aes_string。相反,如果您需要从字符串中获取列值,请使用 .data 代词

ggplot(data=mydat, aes(x=,.data[[xcol]], y=.data[[ycol]])) + geom_point()

原始答案:传递给aes_string 的值是parse()-d。这是因为您可以传递 aes_string(x="log(price)") 之类的内容,而您传递的不是列名而是表达式。因此,它将您的字符串视为表达式,当它解析它时,它会找到空格,这是一个无效的表达式。您可以通过将列名括在引号中来“解决”此问题。例如,这有效

mydat <- data.frame(`Col 1`=1:5, `Col 2`=1:5, check.names=F)
xcol <- "Col 1"
ycol <- "Col 2"
ggplot(data=mydat, aes_string(x=shQuote(xcol), y=shQuote(ycol))) + geom_point()

我们只是使用shQuote() 来为我们的值加上双引号。您也可以像在另一个示例中那样在字符串中嵌入单个刻度

mydat <- data.frame(`Col 1`=1:5, `Col 2`=1:5, check.names=F)
xcol <- "`Col 1`"
ycol <- "`Col 2`"
ggplot(data=mydat, aes_string(x=xcol, y=ycol)) + geom_point()

但真正最好的处理方法是不要使用无效变量名的列名。

【讨论】:

  • 谢谢,是时候重新熟悉一下 tidyverse =/
  • 好吧,这不再是“tidyverse”做事的方式了。这是传统的 ggplot 方式。使用现代 tidyverse 编程,您将使用 quosures(或 expr()sym())并将它们扩展为 aes()。不过,对于带有空格的列名仍然没有真正的帮助。那些只是邪恶的。
  • 我不同意带空格的名称是“无效的变量名称”。例如,您可以这样做:`x 2` &lt;- 1 或使用显式分配给全局环境而不会出现问题。
  • @thc 好的。我想我的意思是不需要用引号括起来的变量名。如果不输入引号,则永远不能使用该名称。大多数人不遗余力地避免一些额外的字符(ala 非标准评估)
  • @thc 我的意思是您也可以使用`4$.^` &lt;- 3,但我不愿意将其称为有效变量名。滴答声确实可以让您规避正常的变量名称规则。
【解决方案2】:

这是一个 tidyeval 方法,这是 tidyverse 开发团队正在向 in place of aes_ or aes_string 发展的方法。 Tidyeval 一开始很棘手,但很漂亮well documented

This recipe sheet 不是 ggplot 特有的,但它在我的书签工具栏上,因为它非常方便。

在这种情况下,您想编写一个函数来处理您的绘图。此函数将一个数据框和两个裸列名称作为参数。然后用enquo 将列名转换为引号,然后!! 取消引用它们以在aes 中使用。

library(ggplot2)

mydat <- data.frame(`Col 1`=1:5, `Col 2`=1:5, check.names=F)

pts <- function(data, xcol, ycol) {
  x_var <- enquo(xcol)
  y_var <- enquo(ycol)
  ggplot(data, aes(x = !!x_var, y = !!y_var)) +
    geom_point()
}

pts(mydat, `Col 1`, `Col 2`)

但也像@MrFlick 所说,尽你所能只使用有效的列名,因为为什么不呢?

【讨论】:

  • 谢谢。这主要是因为read_xl 保留了空格,并且不必重新标记轴。
  • 但是在绘图中添加labs 行可能比编写整个 tidyeval 包装函数更容易,不是吗?
  • 能够做到这一点仍然很有用,因为您可能正在编写一个 R 包的最终用户将使用的绘图函数,并且自动在图上设置看起来不好看的轴标签很好像程序员变量名一样,让您的最终用户不必自己手动添加漂亮的labs
【解决方案3】:

如果列名碰巧包含空格或一些数学符号,如 &gt;&lt;=,它可能仍然关心的人,一个简单的解决方法是在传递时用 as.name() 包装你的字符串发给aes_string()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多