ggplot2 中有没有办法将文本放在弯曲的路径上?

互联网 行业动态 更新时间:2024-06-13 00:19:32

All*_*ron 43

好问题。我经常思考这个问题。我不知道有任何本地允许它的包,但是自己做并不是很困难,因为它被geom_text认为angle是一种美学映射。

假设我们有以下情节:

library(ggplot2)

df <- data.frame(y = sin(seq(0, pi, length.out = 100)),
                 x = seq(0, pi, length.out = 100))

p <- ggplot(df, aes(x, y)) + 
  geom_line() + 
  coord_equal() +
  theme_bw()

p

以及我们想要沿着它运行的以下标签:

label <- "PIRATES VS NINJAS"

我们可以将标签拆分为字符:

label <- strsplit(label, "")[[1]]

现在是棘手的部分。我们需要将字母沿路径均匀分布,这需要计算出实现此目的的 x 坐标。我们在这里需要几个辅助函数:

label <- strsplit(label, "")[[1]]

这些允许我们创建一个包含字母、坐标和角度的小数据框来绘制我们的字母:

next_x_along_sine <- function(x, d)
{
  y <- sin(x)
  uniroot(f = \(b) b^2 + (sin(x + b) - y)^2 - d^2, c(0, 2*pi))$root + x
}
  
x_along_sine <- function(x1, d, n)
{
  while(length(x1) < n) x1 <- c(x1, next_x_along_sine(x1[length(x1)], d))
  x1
}

现在我们可以用普通的 old 进行绘图geom_text

p + geom_text(aes(y = y + 0.1, label = label, angle = angle), data = df2,
              vjust = 1, size = 4, fontface = "bold")

或者,如果我们想用文本替换部分行:

df2 <- as.data.frame(approx(df$x, df$y,  x_along_sine(1, 1/13, length(label))))
df2$label <- label
df2$angle <- atan(cos(df2$x)) * 180/pi

或者,通过一些主题调整:


附录

实际上,我可能不会去写一个geom_textpath包,但我认为根据 OP 的例子展示一种可能适用于标记密度曲线的方法会很有用。它需要以下功能套件:

p + geom_text(aes(y = y + 0.1, label = label, angle = angle), data = df2,
              vjust = 1, size = 4, fontface = "bold")

定义了这些函数后,我们现在可以执行以下操作:

df$col <- cut(df$x, c(-1, 0.95, 2.24, 5), c("black", "white", "#000000"))

ggplot(df, aes(x, y)) + 
  geom_line(aes(color = col, group = col)) + 
  geom_text(aes(label = label, angle = angle), data = df2,
            size = 4, fontface = "bold") +
  scale_color_identity() +
  coord_equal() +
  theme_bw()

@teunbrand 我实际上领先于自己,并根据此处的答案制作了一个 `geom_textpath` 包。您可以通过 `remotes::install_github("AllanCameron/geomtextpath")` 安装它(它通过了 CRAN 检查)并查看 `?geom_textpath` 下的示例。它已经可以做一些非常简洁的事情,尽管我几天前才开始使用它。如果你愿意,我很高兴你将它采用到 ggh4x 中——这还不足以证明它自己的包的合理性,尽管我确实考虑过扩展它以涵盖其他一些用例。 (9认同) @tjebo 和 Allan Cameron 是的,我在 textpath/pathtext grob 中看到了潜力(这也是我问 [this question] 的原因(/sf/ask/4895486431/方向),Allan Cameron 再次没有让您失望!)如果您对 geom 层应该能够做什么有想法,您可以留下建议 [这里](github./teunbrand/ggh4x/issues /58)。 (2认同) 太好了,干得漂亮!我已经看到安装的软件包功能较少,所以它可能是合理的:) (2认同)

All*_*ron 6

最后,这个问题促使我和 Teun van den Brand (@teunbrand) 开发了这个geomtextpath包,它现在在 CRAN 上。

所以现在可以更直接、更简单地回答这个问题:

library(geomtextpath)

ggplot(df, aes(x = duration, color = monthly_run)) + 
  geom_textdensity(aes(label = monthly_run, hjust = monthly_run,
                       vjust = monthly_run), size = 6) +
  scale_hjust_manual(values = c(0.4, 0.55)) +
  scale_vjust_manual(values = c(1.1, -0.2)) +
  scale_y_continuous(limits = c(0, 0.06)) +
  theme_minimal() +
  theme(legend.position = "none")

杰出的!虽然我可能会为包选择不同的名称,例如“ggtextpath”:) (2认同) @tjebo 谢谢。这个名字来自这个问题,一开始似乎很合适。随着范围的扩大,它变得越来越少,但到那时改变它已经太迟了。呃,好吧! (2认同)

更多推荐

放在,中有,没有办法,弯曲,路径

本文发布于:2023-04-21 09:48:07,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/hyzx/4f9de58d5394611b3619bb5a622bc9ef.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:放在   中有   没有办法   弯曲   路径

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!