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认同)
更多推荐
放在,中有,没有办法,弯曲,路径
发布评论