12
$\begingroup$

How can one best create standard Gantt charts in Mathematica, where the horizontal axis is time (preferably in the Mathematica time format) and where one can include labels within each horizontal bar? TimelinePlot and standard BarChart and their relatives, which I've tried, are far too kludgy for this.

$\endgroup$
3
  • 1
    $\begingroup$ There is a specific example in the BarChart documentation showing you how to build a Gantt chart of employee's holidays, but I agree that there's definitely some faff involved... $\endgroup$
    – Carl Lange
    Jun 25, 2018 at 19:57
  • 3
    $\begingroup$ related: Poets of the 19th century -- also related: Timeline plotting: horizontal bars of time intervals $\endgroup$
    – kglr
    Jun 25, 2018 at 20:00
  • 2
    $\begingroup$ It would be helpful if you could add some idea of the data you're looking to place on this chart. $\endgroup$
    – Carl Lange
    Jun 25, 2018 at 20:00

3 Answers 3

8
$\begingroup$

Using the data schedule from @Edmund's answer, (1) wrapping each date range with Labeled and (2) modifying FrameTicks to add additional labels:

ranges = Map[Interval@{First@#, DatePlus @@ #} &, schedule, {2}];
boxlabels = Style[ToUpperCase@#, 12] & /@ RandomWord["Noun", Length[Join @@ schedule]];
labeling = Thread[Join @@ ranges -> boxlabels];
labeledData = Labeled[##, Before]& @@@ # & /@ (Transpose[{#, # /. labeling}] & /@ ranges);
grouplabels = StringTemplate@"GROUP `1`" /@ Range[Length@schedule];
groupsizes = Length /@ ranges;
ticklabels = StringTemplate@"PROJECT `1`" /@ Range[Length[Join @@ schedule]];
spacings = 4;

tlp = TimelinePlot[labeledData, ImageSize -> 700, LabelStyle -> 14, 
    Spacings -> spacings, Frame -> True, 
    PlotMarkers -> {Automatic, 1}, AspectRatio -> 1/GoldenRatio, 
    PlotRangePadding -> {{Scaled[.25], Automatic}, {Scaled[.02], Scaled[.05]}}, 
    PlotLayout -> "Stacked", 
    PlotStyle -> Directive[Thickness[.03], CapForm[None]], 
    PlotLegends -> SwatchLegend[grouplabels],
    GridLines -> {{AbsoluteTime@{2018, 2, 15, 8}}, None}, 
    Method -> {"GridLinesInFront" -> True}] /. Point[__] :> Nothing ;

Show[tlp, Options[tlp[[1]], FrameTicks] /. 
   {None, None} -> {MapIndexed[{ spacings #2[[1]], #} &, ticklabels], 
    MapIndexed[{spacings (Accumulate[groupsizes][[#2[[1]]]] - 
          Floor[groupsizes[[#2[[1]]]]/2]), #} &, grouplabels]}]

enter image description here

$\endgroup$
3
  • $\begingroup$ That is the trick for the FrameTicks for this plot. Would be good if the option worked directly in the plot ; FrameTicks->{{custom, custom}, {Automatic, Automatic}}. I tried that and it did not work. (+1) $\endgroup$
    – Edmund
    Jun 26, 2018 at 11:34
  • $\begingroup$ Thank you @Edmund. I couldn't get FrameTicks work in TimelinePlot either. Also it would have been great if PlotLabels had worked with TimelinePlot. $\endgroup$
    – kglr
    Jun 26, 2018 at 12:19
  • 1
    $\begingroup$ The WFR function ProjectDataGanttChart started with the code in this answer. $\endgroup$ May 21, 2022 at 15:00
15
$\begingroup$

You may use TimelinePlot with the PlotStyle option.

For a project with schedule of start date and duration for a few teams.

SeedRandom[23032]
schedule =
 Partition[
  Transpose@{
    RandomSample[
     DateRange[DateObject@{2018, 2, 1}, DateObject@{2018, 2, 28}, "Day"], 12],
    RandomInteger[{2, 7}, 12]
    },
  3]

Then

TimelinePlot[Map[Interval@{First@#, DatePlus @@ #} &, schedule, {2}],
 PlotStyle -> Thickness@[email protected],
 PlotLegends -> SwatchLegend[Automatic, StringTemplate@"Team `1`" /@ Range@4]]

Mathematica graphics

Additional formatting can be added by referring to the documentation.

Hope this helps.

$\endgroup$
3
  • $\begingroup$ Almost what I need. I would like to 1) label each individual bar (not just all red bars, or all green bars with a legend), and (as with all Gantt charts) label along the left side general topics such as "Project 1", "Project 2" and so on. NOT a legend. (It is sort of surprising that Mathematica does not have a Gantt chart function, since it is so widely used.) $\endgroup$ Jun 26, 2018 at 2:19
  • $\begingroup$ @DavidG.Stork You can use PlotLayout -> "Stacked" and Frame -> All. Then Epilog some frame labels on labels on it. I tried FrameTicks but it does not seem to like it. $\endgroup$
    – Edmund
    Jun 26, 2018 at 2:52
  • 1
    $\begingroup$ I can't seem to get your comment ideas to work, especially if the labels have different length so that mutual alignment is extremely difficult. If you could craft a single, minimal example that had all those features, I'd be grateful (and accept your solution). $\endgroup$ Jun 26, 2018 at 4:48
8
$\begingroup$

We can use Wolfram Function Repository (WFR) function ProjectDataGanttChart.

Here is an example:

SeedRandom[99];
dsProj = 
 ResourceFunction[“RandomTabularDataset"][
  {10, {"Group", "Project", "StartDate", "EndDate"}}, 
  "Generators" -> {
     ResourceFunction["RandomPetName"][3], 
     RandomWord[6], 
     Table[ResourceFunction["RandomDate"][], #] &, 
     Table[ResourceFunction["RandomDate"][], #] &}]

ResourceFunction["ProjectDataGanttChart"][dsProj]

enter image description here

(Hovering with the mouse on the project bars shows start-and-end-times tooltips.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.