如何在GGPLOT2传奇中向后和向前的方向显示箭头?

发布于 2025-02-10 03:34:51 字数 951 浏览 2 评论 0 原文

我有一个 dataFrame ,上面有箭头的坐标:

arrows = data.frame(direction = factor(c("forward", "backward", "backward")),
                x = c(0, 0, 0),
                xend = c(1, 1, 1),
                y = c(1, 1.2, 1.1),
                yend = c(1, 1.2, 1.1))

我想使用此数据绘制箭头 - 有些朝向前进方向,反之亦然。

到目前为止,我尝试了

library(ggplot2)

ggplot() +
        geom_segment(data = arrows, 
                     aes(x, y, xend = xend, yend = yend, col = direction),
                     arrow = arrow(length = unit(0.3, "cm"), type = "closed", ends = c("last", "first")))

”在此处输入图像说明“

我想在此图中解决两个问题:

  1. 我如何确保 ggplot '理解' “前进”和“向后”,所以它给了他们正确的传奇吗?

  2. 如何更改图例,以便它以向前向前的箭头和向后的向后箭头显示向前的方向?

I have a dataframe with coordinates of arrows:

arrows = data.frame(direction = factor(c("forward", "backward", "backward")),
                x = c(0, 0, 0),
                xend = c(1, 1, 1),
                y = c(1, 1.2, 1.1),
                yend = c(1, 1.2, 1.1))

I want to use this data to plot arrows - some goes in the forward direction and vice versa.

So far I tried:

library(ggplot2)

ggplot() +
        geom_segment(data = arrows, 
                     aes(x, y, xend = xend, yend = yend, col = direction),
                     arrow = arrow(length = unit(0.3, "cm"), type = "closed", ends = c("last", "first")))

which produces:

enter image description here

There are 2 problems I want to solve in this plot:

  1. How can I make sure that ggplot 'understands' which plot is "forward" and "backward", so it gives them the right legend?

  2. How to change the legend so that it shows forward direction with an arrow that goes forward, and the backward arrow that goes backward?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

城歌 2025-02-17 03:34:51

也许有两个传说,一个使用自定义字形?

draw_key_arrow_left <- function(data, params, size, dir) {
  if (is.null(data$linetype)) {
    data$linetype <- 0
  } else {
    data$linetype[is.na(data$linetype)] <- 0
  }
  
  segmentsGrob(0.9, 0.5, 0.1, 0.5,
               gp = gpar(
                 col = alpha(data$colour %||% data$fill %||% "black", data$alpha),
                 # the following line was added relative to the ggplot2 code
                 fill = alpha(data$colour %||% data$fill %||% "black", data$alpha),
                 lwd = (data$size %||% 0.5) * .pt,
                 lty = data$linetype %||% 1,
                 lineend = "butt"
               ),
               arrow = params$arrow
  )
}


arrows2 <- arrows %>%
  mutate(x_orig = x, xend_orig = xend,
         x = if_else(direction == "forward", x_orig, xend_orig),
         xend = if_else(direction == "forward", xend_orig, x_orig))

ggplot() +
  geom_segment(data = arrows2 %>% filter(direction == "forward"),
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed")) +
  scale_color_manual(values = "#F8766D") +
  
  ggnewscale::new_scale_color() +
  geom_segment(data = arrows2 %>% filter(direction == "backward"),
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed"),
               key_glyph = "arrow_left") +
  scale_color_manual(values = "#619CFF", name = "") +
  theme(legend.key.width=unit(0.7,"cm"))

Perhaps with two legends, one using a custom glyph?

enter image description here

draw_key_arrow_left <- function(data, params, size, dir) {
  if (is.null(data$linetype)) {
    data$linetype <- 0
  } else {
    data$linetype[is.na(data$linetype)] <- 0
  }
  
  segmentsGrob(0.9, 0.5, 0.1, 0.5,
               gp = gpar(
                 col = alpha(data$colour %||% data$fill %||% "black", data$alpha),
                 # the following line was added relative to the ggplot2 code
                 fill = alpha(data$colour %||% data$fill %||% "black", data$alpha),
                 lwd = (data$size %||% 0.5) * .pt,
                 lty = data$linetype %||% 1,
                 lineend = "butt"
               ),
               arrow = params$arrow
  )
}


arrows2 <- arrows %>%
  mutate(x_orig = x, xend_orig = xend,
         x = if_else(direction == "forward", x_orig, xend_orig),
         xend = if_else(direction == "forward", xend_orig, x_orig))

ggplot() +
  geom_segment(data = arrows2 %>% filter(direction == "forward"),
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed")) +
  scale_color_manual(values = "#F8766D") +
  
  ggnewscale::new_scale_color() +
  geom_segment(data = arrows2 %>% filter(direction == "backward"),
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed"),
               key_glyph = "arrow_left") +
  scale_color_manual(values = "#619CFF", name = "") +
  theme(legend.key.width=unit(0.7,"cm"))
偏爱你一生 2025-02-17 03:34:51

如何将“方向”映射到“第一个”和“最后”,例如,

ggplot() +
  geom_segment(data = arrows, 
                 aes(x = x, xend = xend, y = y, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed", ends = ifelse(arrows$direction == "forward", "first", "last" ))) +
  scale_colour_manual(values = c("darkred", "darkblue"), labels = c("forward", "backward"))

我还使用 scale_colour_manual 来控制哪个方向是向前且向后的。

关于传说中的自定义字形的另一个问题 - - 这应该允许不同的箭头方向,但可能不值得。

How about mapping the "direction" to "first" and "last" directly, e.g.

ggplot() +
  geom_segment(data = arrows, 
                 aes(x = x, xend = xend, y = y, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed", ends = ifelse(arrows$direction == "forward", "first", "last" ))) +
  scale_colour_manual(values = c("darkred", "darkblue"), labels = c("forward", "backward"))

I'd also used a scale_colour_manual to control which direction is forward and which backward.

Another question on SO asked about custom glyphs in legends - show filled arrow in legend ggplot - This should allow the different arrow direction, but might not be worth the effort.

揪着可爱 2025-02-17 03:34:51

需要为每个箭头设置端的参数,而您的末端仅是两个长度,因此最后一个箭头将是错误的方向,因为它使用的是“最后”的默认值,但是由于箭头向后移动,它应该是“第一个”

arrows <- data.frame(direction = (c("forward", "backward", "backward")),
                    x = c(0, 0, 0),
                    xend = c(1, 1, 1),
                    y = c(1, 1.2, 1.1),
                    yend = c(1, 1.2, 1.1))

arrow_head <- function(direction) {
  if(direction == "backward") {
    return("first")
  } else {
    return("last")
  }
}

ggplot() +
  geom_segment(data = arrows,
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed", ends = lapply(arrows$direction, arrow_head)))

The ends argument needs to be set for each arrow, yours is only length two so that last arrow will be the wrong direction since it is using the default which is "last" but since the arrow goes backwards it should be "first"

arrows <- data.frame(direction = (c("forward", "backward", "backward")),
                    x = c(0, 0, 0),
                    xend = c(1, 1, 1),
                    y = c(1, 1.2, 1.1),
                    yend = c(1, 1.2, 1.1))

arrow_head <- function(direction) {
  if(direction == "backward") {
    return("first")
  } else {
    return("last")
  }
}

ggplot() +
  geom_segment(data = arrows,
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed", ends = lapply(arrows$direction, arrow_head)))

enter image description here

菊凝晚露 2025-02-17 03:34:51

您可以根据方向列以X/XEND交换列值。

library(tidyverse)
arrows = data.frame(direction = factor(c("forward", "backward", "backward")),
                    x = c(0, 0, 0),
                    xend = c(1, 1, 1),
                    y = c(1, 1.2, 1.1),
                    yend = c(1, 1.2, 1.1))

## thanks for the idea https://stackoverflow.com/questions/51096664/how-to-do-conditional-swapping-using-two-columns
swap_direction <- function(data){
  swap <- data$direction == "backward"
  v1 <- data$x
  v2 <- data$xend
  data$x[swap] <- v2[swap]
  data$xend[swap] <- v1[swap]
  data
}
reversed_arrows <- swap_direction(arrows)

ggplot() +
  geom_segment(data = reversed_arrows, 
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed"))

“”

在2022-06-28上创建的 reprex软件包(v2.0.1)

You could swap the column values in x/xend based on the direction column.

library(tidyverse)
arrows = data.frame(direction = factor(c("forward", "backward", "backward")),
                    x = c(0, 0, 0),
                    xend = c(1, 1, 1),
                    y = c(1, 1.2, 1.1),
                    yend = c(1, 1.2, 1.1))

## thanks for the idea https://stackoverflow.com/questions/51096664/how-to-do-conditional-swapping-using-two-columns
swap_direction <- function(data){
  swap <- data$direction == "backward"
  v1 <- data$x
  v2 <- data$xend
  data$x[swap] <- v2[swap]
  data$xend[swap] <- v1[swap]
  data
}
reversed_arrows <- swap_direction(arrows)

ggplot() +
  geom_segment(data = reversed_arrows, 
               aes(x, y, xend = xend, yend = yend, col = direction),
               arrow = arrow(length = unit(0.3, "cm"), type = "closed"))

Created on 2022-06-28 by the reprex package (v2.0.1)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文