Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Hi does anyone know how to make timelines with mathematica?

http://images.nationmaster.com/images/motw/atlas_middle_east/turkey_timeline.jpg

something like that would be great! thanks

share|improve this question
6  
What have you tried so far? –  Mr.Wizard Jun 14 '12 at 13:15
3  
@belisarius I think it's a reasonable task for Mathematica with some potentially interesting solutions. –  Mr.Wizard Jun 14 '12 at 13:17
3  
This is clearly doable, and not very difficult, but it's a lot of work. It's much more likely that you'll get an answer if you first try to implement it on your own, show us what you have, and ask about the specific point you got stuck at. –  Szabolcs Jun 14 '12 at 13:34
3  
In agreement with Szabolcs I would suggest you try out on your own first. Look up the documentation for Graphics, Line and Text, it's really just a task of combining these depending on your input list. –  jVincent Jun 14 '12 at 13:38
3  
This presentation, Dynamic Timeline Plots, by Daniel G Martinez, may be of interest. –  TomD Jun 14 '12 at 14:40

3 Answers 3

up vote 17 down vote accepted

I tried to do something similar a few months ago

The easiest way is to write several functions:


EventFrame function creates event lables

EventFrame[str_, {date_, height_}, OptionsPattern[FontSize -> 14]] := 
Graphics[{
  Black, Thick, Line[{{date, height}, {date, 0}}], 
  Text[Framed[Style[str, FontSize -> OptionValue[FontSize]],
  {Background -> White, FrameStyle -> Black,FrameMargins -> Automatic}], {date, height}]
}]

DateConv converts date {yr,mon,day} into single real number

Needs["Calendar`"]
LeapYearQ[year_] := DateQ[{year, 2, 29}]
DateConv[y_, m_, d_]:=y+(DateDifference[{y},{y, m, d}]+1)/If[LeapYearQ[y], 366, 365]
DateConv[{y_, m_, d_}]:=y+(DateDifference[{y},{y, m, d}]+1)/If[LeapYearQ[y], 366, 365]

TimeLine function creates timeline

TimeLine[min_, max_] := 
Graphics[{ 
  (* TimeLine *)
  Black, Thick, Line[{{min, 0}, {max, 0}}], 
  (* year ticks *)
  Thin, Table[Line[{{x, 0.5}, {x, 0}}], {x, min, max}],
  (* year labels *)
  Table[Text[Framed[Style[x, FontSize -> 20],
  {Background -> White, FrameStyle -> White}], {x, 1}], {x, min, max}]
}]

Now all we need is a Show function. Use Pane for for easier viewing

Pane[Show[
    EventFrame["Event 1", {DateConv[1988, 6, 2], 4}],
    EventFrame["Event 2", {DateConv[1990, 8, 15], -2}],
    (************************)
    TimeLine[1985, 1995],
    (************************)
     AspectRatio -> 1/6, ImageSize -> {1400, 280}],
    (************************)
    ImageSize -> {550, 280}, Scrollbars -> {True, False}]

Output without Pane enter image description here

Edit

EventFrame2 function

EventFrame2[str_, {date_, height_}, OptionsPattern[{FontSize -> 14, offsets -> {0, 0}}]] := 
Graphics[{
  Thick,Line[{{date, height}, {date, 0}}], 
  Text[Framed[Style[Column@{Style[ToString[Floor[date]],
  Bold,TextAlignment -> Left], str}, 
  FontSize -> OptionValue[FontSize]],
 {Background -> White, FrameStyle -> Black,FrameMargins -> Automatic}],
{date, height},OptionValue[offsets]]
} ]

Example

EventFrame2["Event 1", {DateConv[1988, 6, 2], 4}, offsets -> {-0.97, -0.5}]

enter image description here


Update 2014 - Mathematica 10

LeapYearQ is now a standard Mathematica function.

DateDifferencenow returns Quantity[n_,"Days"]

New DateConv function:

DateConv[y_, m_, d_] := 
 y + (DateDifference[{y}, {y, m, d}][[1]] + 1)/If[LeapYearQ[y], 366, 365]
share|improve this answer
2  
Does this handle leap years? The division by 365 in DateConv makes me wonder. –  Verbeia Jun 14 '12 at 22:25
    
Thanks, I forgot about that. Added LeapYearQ function –  FDSg Jun 15 '12 at 0:43
1  
Instead of DateConv[], you might consider the use of AbsoluteTime[]... –  J. M. Jun 17 '12 at 3:12
    
this is fantastic. some ideas i'm going to try to implement: tooltip for difference between dates, title and eventually tagging. my original idea was to have certain events with tags like : event 1 - green tag, red tag, yellow tag; event 2 - green tag; event 3 - red tag; when red tag is selected only events 1 and 2 are displayed. in that vein. will begin work and modifications tonight –  user582 Jun 19 '12 at 23:40
    
what exactly does the second DateConv[] function do? DateConv[{y_, m_, d_}]:=y+(DateDifference[{y},{y, m, d}]+1)/If[LeapYearQ[y], 366, 365] –  user582 Jun 19 '12 at 23:53

enter image description here

Based on data in Comm ACM. This took a while to only partially automate, largely through a helper function that spreads out the years:

diffuse[a_][years_List] := 
  Module[{x0 = 1, x1 = Length[years], y0 = Min[years], 
    y1 = Max[years]},
   years // 
    MapIndexed[ {#1, (((y1 - y0)/(x1 - x0))*(First[#2] - x0) + 
           y0) a + (#1) (1 - a)} &]]; 

diffuse maps a list of time points and spreads the interor points. The parameter a in principle can be any real number but higher values in [0,1] correspond to increasingly uniform spacing.

is defined in op form for use in Dataset:

data = {<|"Year" -> 1906, "Author" -> "Markov", "Contribution" -> "Markov theory"|>, <|"Year" -> 1907, "Author" -> "Perron","Contribution" -> "Perron theorem"|>, <|"Year" -> 1912, "Author" -> "Frobenius", "Contribution" -> "Perron-Frobenius theorem"|>, <|"Year" -> 1929, "Author" -> "von Mises", "Contribution" -> "Power method"|>, <|"Year" -> 1941,"Author" -> "Leontief",  "Contribution" -> "Econometric model"|>, <|"Year" -> 1949,  "Author" -> "Seeley", "Contribution" -> "Sociometric model"|>, <|"Year" -> 1952, "Author" -> "Wei", "Contribution" -> "Sport ranking model"|>, <|"Year" -> 1953, "Author" -> "Katz", "Contribution" -> "Sociometric model"|>, <|"Year" -> 1965, "Author" -> "Hubbell", "Contribution" -> "Sociometric model"|>, <|"Year" -> 1976,  "Author" -> "Pinsk, Narin",  "Contribution" -> "Bibliometric model"|>, <|"Year" -> 1998, "Author" -> "Kleinberg", "Contribution" -> "HITS"|>, <|"Year" -> 1998, "Author" -> "Brin, Page", "Contribution" -> "PageRank"|>} //Dataset;

Some years cluster:

data[All, "Year"] // Normal // NumberLinePlot

enter image description here

Make interpolation function (alternatively, can define an Association)

shift = data[
  GroupBy[#Year &] /* Keys /* diffuse[0.35] /* Interpolation]

Values a ~ 1/3 work for this particular data and graphics w/ coorindated shift:

itemGraphics := {{Darker@Blue, Disk[{#Year, 0}, 0.25]},
   {Thickness[0.001], Opacity[0.5], 
    BezierCurve[{{#Year, 0}, {#Year, 2}, {shift[#Year], 
       1 + 3/4}, {shift[#Year], 1 + 3/2}, {shift[#Year], 3}}]},
   Text[Column[{Style[ToLowerCase@#Author, Darker@Blue, 
       FontSize -> 14, Bold], 
      Style[ToLowerCase@#Contribution, Small]}, 
     Spacings -> 0], {shift[#Year], 4}, {-1, 1/2}, {1, 1}, 
    BaseStyle -> None]} &

Layout w/o timeline shows label clashing :

data[Graphics, itemGraphics]

enter image description here

data[GroupBy[#Year &]][Values, 
   MapIndexed[Translate[#1, {0, 6 (First[#2] - 1)}] &], itemGraphics] // 
  Normal // Graphics[{#}, Axes -> {True, False}, 
   PlotRange -> {{1900, 2020}, All}, 
   TicksStyle -> Directive@{FontSize -> 15, Darker@Blue}, 
   ImageSize -> 1000, ImagePadding -> 50] & 

enter image description here

At a=0.7 balloon lines are stretched and spacing is more even but many labels are shifted way off past the years of future events.

enter image description here

This illustrates the interaction of ImageSize, AspectRatio, fonts, and data content (time clustering, ties, label dimensions (no easy way to get bounding boxes) seriously complicates automating layout.

share|improve this answer
2  
Pardon me, but how is this supposed to be used? –  Mr.Wizard Jan 25 at 19:56
1  
@Mr.Wizard, you can similarly ask of many system functions, like how is BarChart supposed to be used in the real world when it never does exactly what you want. In any case added methods. –  alancalvitti Jan 27 at 22:21
    
Thanks for the update. +1 –  Mr.Wizard Jan 27 at 22:24
    
@Mr.Wizard, btw, the Brin & Page baloon line ideally would curve around Kleinberg, but then that graphic component would have to be refactored one Level up. Also there's likely more modular approach naming and processing graphics in Associations. –  alancalvitti Jan 27 at 22:28

As of Mathematica 10.1, creating a timeline is built-in with TimelinePlot[].

TimelinePlot[{
    Labeled[Interval[{DateObject[{2010, 2, 1}], DateObject[{2013, 5, 4}]}], "label1"], 
    Labeled[DateObject[{2012, 4, 6}], "label2"], 
    Labeled[Interval[{DateObject[{2011, 3, 1}], DateObject[{2012, 12, 21}]}], "label3"]
  }]

enter image description here

Lots of possibilities, looking at the documentation!

TimelinePlot[EntityClass["Movie", "BackToTheFutureFranchise"] -> "ReleaseDate"]

enter image description here

share|improve this answer
1  
As of 10.1 TimelinePlot doesn't have a robust layout engine. For example try to display all disasters from here airdisaster.com/cgi-bin/database.cgi, the labels crowd on top of each other so they become unreadable - this can only be avoided by selecting subsets or extreme AspectRatio. Compare to GIS layout engines like Google Maps, where stree names may disappear on zoomout, but don't crowd each other. –  alancalvitti 17 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.