带 R 的甘特图

如何在 R 中创建 甘特图

我正在寻找一些复杂的东西(看起来或多或少像这样) : this

另外,没有依赖箭头我也能活下去。

82901 次浏览

A simple ggplot2 gantt chart.

First, we create some data.

library(reshape2)
library(ggplot2)


tasks <- c("Review literature", "Mung data", "Stats analysis", "Write Report")
dfr <- data.frame(
name        = factor(tasks, levels = tasks),
start.date  = as.Date(c("2010-08-24", "2010-10-01", "2010-11-01", "2011-02-14")),
end.date    = as.Date(c("2010-10-31", "2010-12-14", "2011-02-28", "2011-04-30")),
is.critical = c(TRUE, FALSE, FALSE, TRUE)
)
mdfr <- melt(dfr, measure.vars = c("start.date", "end.date"))

Now draw the plot.

ggplot(mdfr, aes(value, name, colour = is.critical)) +
geom_line(size = 6) +
xlab(NULL) +
ylab(NULL)

Try this:

install.packages("plotrix")
library(plotrix)
?gantt.chart

Package plan supports the creation of burndown charts and gantt diagrams and contains a plot.gantt function. See this R Graphical Manual page

See also how to make one in R using Plotly’s R API GANTT CHARTS IN R USING PLOTLY.

I used and modified the above example from Richie, worked like a charm. Modified version to show how his model could translate into ingesting CSV data rather than manually provided text items.

NOTE: Richie's answer was missing indication that 2 packages ( reshape and ggplot2 ) are needed for the above/below code to work.

rawschedule <- read.csv("sample.csv", header = TRUE) #modify the "sample.csv" to be the name of your file target. - Make sure you have headers of: Task, Start, Finish, Critical OR modify the below to reflect column count.
tasks <- c(t(rawschedule["Task"]))
dfr <- data.frame(
name        = factor(tasks, levels = tasks),
start.date  = c(rawschedule["Start"]),
end.date    = c(rawschedule["Finish"]),
is.critical = c(rawschedule["Critical"]))
mdfr <- melt(dfr, measure.vars = c("Start", "Finish"))




#generates the plot
ggplot(mdfr, aes(as.Date(value, "%m/%d/%Y"), name, colour = Critical)) +
geom_line(size = 6) +
xlab("Duration") + ylab("Tasks") +
theme_bw()

There are now a few elegant ways to generate a Gantt chart in R.

Using Candela

library(candela)


data <- list(
list(name='Do this', level=1, start=0, end=5),
list(name='This part 1', level=2, start=0, end=3),
list(name='This part 2', level=2, start=3, end=5),
list(name='Then that', level=1, start=5, end=15),
list(name='That part 1', level=2, start=5, end=10),
list(name='That part 2', level=2, start=10, end=15))


candela('GanttChart',
data=data, label='name',
start='start', end='end', level='level',
width=700, height=200)

enter image description here

Using DiagrammeR

library(DiagrammeR)


mermaid("
gantt
dateFormat  YYYY-MM-DD
title A Very Nice Gantt Diagram


section Basic Tasks
This is completed             :done,          first_1,    2014-01-06, 2014-01-08
This is active                :active,        first_2,    2014-01-09, 3d
Do this later                 :               first_3,    after first_2, 5d
Do this after that            :               first_4,    after first_3, 5d


section Important Things
Completed, critical task      :crit, done,    import_1,   2014-01-06,24h
Also done, also critical      :crit, done,    import_2,   after import_1, 2d
Doing this important task now :crit, active,  import_3,   after import_2, 3d
Next critical task            :crit,          import_4,   after import_3, 5d


section The Extras
First extras                  :active,        extras_1,   after import_4,  3d
Second helping                :               extras_2,   after extras_1, 20h
More of the extras            :               extras_3,   after extras_1, 48h
")

enter image description here

Find this example and many more on DiagrammeR GitHub


If your data is stored in a data.frame, you can create the string to pass to mermaid() by converting it to the proper format.

Consider the following:

df <- data.frame(task = c("task1", "task2", "task3"),
status = c("done", "active", "crit"),
pos = c("first_1", "first_2", "first_3"),
start = c("2014-01-06", "2014-01-09", "after first_2"),
end = c("2014-01-08", "3d", "5d"))


#   task status     pos         start        end
#1 task1   done first_1    2014-01-06 2014-01-08
#2 task2 active first_2    2014-01-09         3d
#3 task3   crit first_3 after first_2         5d

Using dplyr and tidyr (or any of your favorite data wrangling ressources):

library(tidyr)
library(dplyr)


mermaid(
paste0(
# mermaid "header", each component separated with "\n" (line break)
"gantt", "\n",
"dateFormat  YYYY-MM-DD", "\n",
"title A Very Nice Gantt Diagram", "\n",
# unite the first two columns (task & status) and separate them with ":"
# then, unite the other columns and separate them with ","
# this will create the required mermaid "body"
paste(df %>%
unite(i, task, status, sep = ":") %>%
unite(j, i, pos, start, end, sep = ",") %>%
.$j,
collapse = "\n"
), "\n"
)
)

As per mentioned by @GeorgeDontas in the comments, there is a little hack that could allow to change the labels of the x axis to dates instead of 'w.01, w.02'.

Assuming you saved the above mermaid graph in m, do:

m$x$config = list(ganttConfig = list(
axisFormatter = list(list(
"%b %d, %Y"
,htmlwidgets::JS(
'function(d){ return d.getDay() == 1 }'
)
))
))

Which gives:

enter image description here


Using timevis

From the timevis GitHub:

timevis lets you create rich and fully interactive timeline visualizations in R. Timelines can be included in Shiny apps and R markdown documents, or viewed from the R console and RStudio Viewer.

library(timevis)


data <- data.frame(
id      = 1:4,
content = c("Item one"  , "Item two"  ,"Ranged item", "Item four"),
start   = c("2016-01-10", "2016-01-11", "2016-01-20", "2016-02-14 15:00:00"),
end     = c(NA          ,           NA, "2016-02-04", NA)
)


timevis(data)

Which gives:

enter image description here


Using plotly

I stumbled upon this post providing another method using plotly. Here's an example:

library(plotly)


df <- read.csv("https://cdn.rawgit.com/plotly/datasets/master/GanttChart-updated.csv",
stringsAsFactors = F)


df$Start  <- as.Date(df$Start, format = "%m/%d/%Y")
client    <- "Sample Client"
cols      <- RColorBrewer::brewer.pal(length(unique(df$Resource)), name = "Set3")
df$color  <- factor(df$Resource, labels = cols)


p <- plot_ly()
for(i in 1:(nrow(df) - 1)){
p <- add_trace(p,
x = c(df$Start[i], df$Start[i] + df$Duration[i]),
y = c(i, i),
mode = "lines",
line = list(color = df$color[i], width = 20),
showlegend = F,
hoverinfo = "text",
text = paste("Task: ", df$Task[i], "<br>",
"Duration: ", df$Duration[i], "days<br>",
"Resource: ", df$Resource[i]),
evaluate = T
)
}


p

Which gives:

enter image description here

You can then add additional information and annotations, customize fonts and colors, etc. (see blog post for details)

Library PlotPrjNetworks provides useful Networking Tools for Project Management.

library(PlotPrjNetworks)
project1=data.frame(
task=c("Market Research","Concept Development","Viability Test",
"Preliminary Design","Process Design","Prototyping","Market Testing","Final Design",
"Launching"),
start=c("2015-07-05","2015-07-05","2015-08-05","2015-10-05","2015-10-05","2016-02-18",
"2016-03-18","2016-05-18","2016-07-18"),
end=c("2015-08-05","2015-08-05","2015-10-05","2016-01-05","2016-02-18","2016-03-18",
"2016-05-18","2016-07-18","2016-09-18"))
project2=data.frame(
from=c(1,2,3,4,5,6,7,8),
to=c(2,3,4,5,6,7,8,9),
type=c("SS","FS","FS","SS","FS","FS","FS","FS"),
delay=c(7,7,7,8,10,10,10,10))
GanttChart(project1,project2)

enter image description here

You can do it with the GoogleVis package:

datTL <- data.frame(Position=c(rep("President", 3), rep("Vice", 3)),
Name=c("Washington", "Adams", "Jefferson",
"Adams", "Jefferson", "Burr"),
start=as.Date(x=rep(c("1789-03-29", "1797-02-03",
"1801-02-03"),2)),
end=as.Date(x=rep(c("1797-02-03", "1801-02-03",
"1809-02-03"),2)))


Timeline <- gvisTimeline(data=datTL,
rowlabel="Name",
barlabel="Position",
start="start",
end="end",
options=list(timeline="{groupByRowLabel:false}",
backgroundColor='#ffd',
height=350,
colors="['#cbb69d', '#603913', '#c69c6e']"))
plot(Timeline)

enter image description here

Source: https://cran.r-project.org/web/packages/googleVis/vignettes/googleVis_examples.html

I would like to improve the ggplot-Answer with several bars for each task.

First generate some data (dfrP is the data.frame of the other answer, dfrR is some other data.frame with realisation dates and mdfr is a merge fitting to the following ggplot()-statement):

library(reshape2)
tasks <- c("Review literature", "Mung data", "Stats analysis", "Write Report")
dfrP <- data.frame(
name        = factor(tasks, levels = tasks),
start.date  = as.Date(c("2010-08-24", "2010-10-01", "2010-11-01", "2011-02-14")),
end.date    = as.Date(c("2010-10-31", "2010-12-14", "2011-02-28", "2011-04-30")),
is.critical = c(TRUE, FALSE, FALSE, TRUE)
)
dfrR <- data.frame(
name        = factor(tasks, levels = tasks),
start.date  = as.Date(c("2010-08-22", "2010-10-10", "2010-11-01", NA)),
end.date    = as.Date(c("2010-11-03", "2010-12-22", "2011-02-24", NA)),
is.critical = c(TRUE, FALSE, FALSE,TRUE)
)
mdfr <- merge(data.frame(type="Plan", melt(dfrP, measure.vars = c("start.date", "end.date"))),
data.frame(type="Real", melt(dfrR, measure.vars = c("start.date", "end.date"))), all=T)

Now plot this data using facets for the task name:

library(ggplot2)
ggplot(mdfr, aes(x=value, y=type, color=is.critical))+
geom_line(size=6)+
facet_grid(name ~ .) +
scale_y_discrete(limits=c("Real", "Plan")) +
xlab(NULL) + ylab(NULL)

Without the is.critical-information you could also use Plan/Real as color (which I would prefere), but I wanted to use the data.frame of the other answer to make it better comparable.

For me, Gvistimeline was the best tool to do this, but its required online connection was not useful to me. Thus I created a package called vistime that uses plotly (similar to the answer of @Steven Beaupré), so you can zoom in etc.:

https://github.com/shosaco/vistime

vistime: Create interactive timelines or Gantt charts using plotly.js. The charts can be included in Shiny apps and manipulated via plotly_build().

install.packages("vistime")
library("vistime")


dat <- data.frame(Position=c(rep("President", 3), rep("Vice", 3)),
Name = c("Washington", "Adams", "Jefferson", "Adams", "Jefferson", "Burr"),
start = rep(c("1789-03-29", "1797-02-03", "1801-02-03"), 2),
end = rep(c("1797-02-03", "1801-02-03", "1809-02-03"), 2),
color = c('#cbb69d', '#603913', '#c69c6e'),
fontcolor = rep("white", 3))


vistime(dat, events="Position", groups="Name", title="Presidents of the USA")

enter image description here

Consider to use the package projmanr (version 0.1.0 released on CRAN on 23 Aug 2017).

library(projmanr)


# Use raw example data
(data <- taskdata1)

taskdata1:

  id name duration pred
1  1   T1        3
2  2   T2        4    1
3  3   T3        2    1
4  4   T4        5    2
5  5   T5        1    3
6  6   T6        2    3
7  7   T7        4 4,5
8  8   T8        3  6,7

Now start to prepare gantt:

# Create a gantt chart using the raw data
gantt(data)

enter image description here

# Create a second gantt chart using the processed data
res <- critical_path(data)
gantt(res)

enter image description here

# Use raw example data
data <- taskdata1
# Create a network diagram chart using the raw data
network_diagram(data)

enter image description here

# Create a second network diagram using the processed data
res <- critical_path(data)
network_diagram(res)

enter image description here

Found the geom_segment in ggplot is great. From the previous solutions use the data but no need to melt.

library(ggplot2)


tasks <- c("Review literature", "Mung data", "Stats analysis", "Write Report")
dfr <- data.frame(
name        = factor(tasks, levels = tasks),
start.date  = as.Date(c("2010-08-24", "2010-10-01", "2010-11-01", "2011-02-14")),
end.date    = as.Date(c("2010-10-31", "2010-12-14", "2011-02-28", "2011-04-30")),
is.critical = c(TRUE, FALSE, FALSE, TRUE)
)


ggplot(dfr, aes(x =start.date, xend= end.date, y=name, yend = name, color=is.critical)) +
geom_segment(size = 6) +
xlab(NULL) + ylab(NULL)

GantPlot

Very old question, I know, but perhaps worth leaving here that - unsatisfied with the answers I found to this question - a few months ago I made a basic package for making ggplot2-based Gantt charts: ganttrify (more details in the package's readme).

Example output: enter image description here