【问题标题】:ggplot: re-order categorical y-axis (Gantt chart)ggplot:重新排序分类y轴(甘特图)
【发布时间】:2021-03-04 13:00:45
【问题描述】:

我正在尝试从具有不同任务(每个都有开始日期和结束日期)的表中生成甘特图。

library(tidyverse)

# Sample data
df1 <- data.frame(from = c("2020-01-01", "2020-02-02", "2020-05-04", "2020-02-01", "2020-01-20", "2020-02-10"),
                  to =   c("2020-03-30", "2020-03-15", "2020-05-20", "2020-04-05", "2020-03-05", "2020-04-13"),
                  task= c("Task 1", "Task 2", "Task 3", "Task 4", "Task 5", "Task 6"),
                  group = c("Finance", "Finance", "Research", "Research", "Other", "Other")
)

# Plot gantt-chart
df1 %>% mutate(from = as.Date(from),
               to = as.Date(to)) %>% 
  pivot_longer(cols = c(from, to), values_to = "date") %>%
  ggplot(aes(x=date, y=task, colour = group)) + 
  geom_line(lwd=3) +
  geom_point(aes(color=group), alpha=.5, pch=18, size=5) +
  scale_x_date(position="bottom", date_breaks = "1 week", date_labels="%U") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5))+
  ggtitle("Milestones") +
  labs(y="", x = "", colour="Responsible")

到目前为止一切顺利,但现在我有一个主要问题和一个小问题:

主要问题:

  • 如何在 y 轴上重新排序出现在数据中的类别(不按字母顺序)?从上到下应该是:金融、研究、其他。此外,在每个类别(金融、研究、其他)中,行应按开始日期排序(即首先开始的任务应位于顶部)

小问题:

  • 如何在 x 轴上绘制每个月的粗线和每周的细线?

感谢您的帮助!

【问题讨论】:

  • 1) library(tidyverse) 也加载了ggplot2,不需要显式加载; 2)按分类变量对轴进行排序,将其定义为具有所需级别顺序的因子,ggplot 将保持该顺序,请参阅this SO post。

标签: r ggplot2 tidyverse


【解决方案1】:

这可以这样实现:

  1. 正如@RuiBarrades 在他的 cmets 中提到的,要获得正确的顺序,您必须转换为一个因子并以正确的顺序设置水平。首先,设置组的级别。其次,为了按所需顺序获得任务,我按组和开始日期重新排列数据集,并利用forcats::fct_inorder 按所需顺序设置任务级别。

  2. 如果我没听错的话,您想要每周和每月使用不同的网格线吗?这可以通过设置date_breaks_minor="month" 和通过theme 和panel.grid.minor/major.x 设置网格线的样式来实现。在这里,我选择了“黑色”颜色,但如果您喜欢不同的尺寸,您可以通过size 进行操作。

library(tidyverse)
library(ggplot2)

# Sample data
df1 <- data.frame(from = c("2020-01-01", "2020-02-02", "2020-05-04", "2020-02-01", "2020-01-20", "2020-02-10"),
                  to =   c("2020-03-30", "2020-03-15", "2020-05-20", "2020-04-05", "2020-03-05", "2020-04-13"),
                  task= c("Task 1", "Task 2", "Task 3", "Task 4", "Task 5", "Task 6"),
                  group = c("Finance", "Finance", "Research", "Research", "Other", "Other")
)

# Plot gantt-chart
df1 %>% mutate(from = as.Date(from),
               to = as.Date(to),
               group = factor(group, levels = c("Finance", "Research", "Other"))) %>%
  arrange(desc(group), desc(from)) %>% 
  mutate(task = forcats::fct_inorder(task)) %>% 
  pivot_longer(cols = c(from, to), values_to = "date") %>%
  ggplot(aes(x=date, y=task, colour = group)) + 
  geom_line(lwd=3) +
  geom_point(aes(color=group), alpha=.5, pch=18, size=5) +
  scale_x_date(position="bottom", date_breaks = "1 week", date_minor_breaks = "1 month",
               date_labels="%U") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5), 
        panel.grid.minor.x = element_line(color = "black"))+
  ggtitle("Milestones") +
  labs(y="", x = "", colour="Responsible")

【讨论】:

  • 关于“forcats::fct_inorder(task)”部分的重要提示。在规模上比在给定潜在范围的情况下使用与 Group/Responsible 相同的方法要好得多。 OP - 如果您要从数据框中制作多个图形/项目,则将前向管道 (%>%) 从图形调用中取出,并使用自身作为因子版本覆盖 df 组列。
  • 哇,太棒了!非常感谢。只是一个后续问题:为什么月份的行不完全在周的刻度上?
  • 那是因为通常几周不会从一个月的开始开始,当然因为一个月大约是一个月。大约等于 4.33 周。
  • ...但您可以尝试使用scale_x_date(position="bottom", date_breaks = "4 weeks", date_minor_breaks = "1 week" 并使用panel.grid.major.x = element_line(color = "black") 而不是panel.grid.minor.x,而不是一个月使用4 周。
猜你喜欢
  • 2014-07-02
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 2018-07-20
  • 2021-03-14
相关资源
最近更新 更多