7

I am not sure timeline is the appropriate term here. I would like to do something like that:

enter image description here

But all the answers I have found here seem to be about one dimensional timelines, so maybe what I am looking to do is not a timeline.

I know a bit of TikZ so I can probably do multiple rectangles but that seems a bit tedious, and I wonder if there are simpler ways

EDIT: Database

Here is the start of the database I would like to represent. Ideally, there would be two kind of representations as threre are two kind of elements to represent: authors and events

*Auteur*    
Jean Bodin  ,   1530    ,   1596
Jean Bénigne Bossuet    ,   1627    ,   1704
Richelieu   ,   1585    ,   1642
Louis XIV   ,   1638    ,   1715
Thomas Hobbes   ,   1588    ,   1679
John Locke  ,   1632    ,   1704
Montesquieu ,   1689    ,   1755
Franois Quesnay ,   1694    ,   1774
Bayle   ,   1647    ,   1706
Voltaire    ,   1694    ,   1778
Frédéric II de Prusse   ,   1712    ,   1789
Joseph II   ,   1706    ,   1790
Catherine II    ,   1729    ,   1796
Jean-Jacques Rousseau   ,   1712    ,   1778
Sieyès  ,   1748    ,   1836
Robespierre ,   1758    ,   1794

*Evenement* 
Guerres de religion ,   1562    ,   1598
Saint Barthélémy    ,   23 Aout 1572    ,   
Guerre de Trente ans    ,   1618    ,   1648
Fronde  ,   1648    ,   1653
Invincible armada   ,   1588    ,   
Grande Rébellion    ,   1642    ,   1649
Glorieuse Révolution    ,   1688    ,   1689
  • 2
    Looks kind of like a Gantt chart (see pgfgantt package). Would probably not be so hard with a loop in TikZ either. Might be doable with pgfplots as well. Do you have any specific data you want to visualize? Can you show/make an example of the data at least, making dummy datasets is tedious at times. – Torbjørn T. Jan 19 '17 at 10:30
  • I have added a list, but I am not sure I have done it the best way possible – Anthony Martin Jan 19 '17 at 10:54
  • My first thought is that it might be easier if the data was comma separated, i.e. <name/label>,<start year>,<end year>. Makes parsing it easier, I think. – Torbjørn T. Jan 19 '17 at 11:37
12

Round 3 -- pgfplotstable + TikZ with some sort of handling of single time entries.

Ok, this isn't brilliant, but there is a very basic handling of single time entries. It does require some modification to the input though. I don't know how to parse a date like 23 Aout 1572, so for simplicity I set the startyear to a decimal value, 1572.65. (No, it's not exact, but that really wont matter much for the display.) The endyear is set to -1, and used as a flag to determine whether to draw a rectangle or something else.

So I first read in the two tables with pgpflotstable, then append a new column to each of those containing a color specification. I merge the two, and sort them.

If you want the two groups separate, but sorted within each group, sort each of those tables separately, and merge the sorted tables. If you don't need sorting at all, just merge the two tables.

Using a loop similar to that in https://tex.stackexchange.com/a/20500/586, I draw a visualization of each entry. If endyear is -1, I draw a circle, else a rectangle.

enter image description here

\documentclass{article}
\usepackage{tikz, pgfplotstable}
\usetikzlibrary{arrows.meta}
\usepackage[utf8]{inputenc}

% read in table
\pgfplotstableread[col sep=comma]{
label,startyear,endyear
Jean Bodin  ,   1530    ,   1596
Jean Bénigne Bossuet    ,   1627    ,   1704
Richelieu   ,   1585    ,   1642
Louis XIV   ,   1638    ,   1715
Thomas Hobbes   ,   1588    ,   1679
John Locke  ,   1632    ,   1704
Montesquieu ,   1689    ,   1755
Francois Quesnay ,   1694    ,   1774
Bayle   ,   1647    ,   1706
Voltaire    ,   1694    ,   1778
Frédéric II de Prusse   ,   1712    ,   1789
Joseph II   ,   1706    ,   1790
Catherine II    ,   1729    ,   1796
Jean-Jacques Rousseau   ,   1712    ,   1778
Sieyès  ,   1748    ,   1836
Robespierre ,   1758    ,   1794
}\authors

\pgfplotstableread[col sep=comma]{
label,startyear,endyear
Guerres de religion ,   1562    ,   1598
Guerre de Trente ans    ,   1618    ,   1648
Saint Barthélémy    ,   1572.65    ,  -1
Fronde  ,   1648    ,   1653
Invincible armada   ,   1588    ,   -1
Grande Rébellion    ,   1642    ,   1649
Glorieuse Révolution    ,   1688    ,   1689
}\events

% add color columns
\pgfplotstablecreatecol[create col/set={blue!30}]{color}{\authors}
\pgfplotstablecreatecol[create col/set={red!30}]{color}{\events}

% append events table to authors table
\pgfplotstablevertcat{\authors}{\events}
% sort by startyear
\pgfplotstablesort[sort key=startyear]\sortedtable\authors


\begin{document}
% if you want to look at the table    
%\pgfplotstabletypeset[
% columns/label/.style={string type},
% columns/color/.style={string type}
%]\sortedtable

\noindent\begin{tikzpicture}
\pgfmathsetmacro\yearscale{0.03} % scaling factor for x-values (years)
\pgfmathsetmacro\yscale{0.3} % scaling for y-direction -- effectively vertical distance between bars
\pgfmathsetmacro\barheight{0.25} % height of bars

\pgfplotstablegetrowsof{\sortedtable}
\pgfmathsetmacro{\M}{\pgfplotsretval-1}
\pgfplotstablegetcolsof{\sortedtable}
\pgfmathsetmacro{\N}{\pgfplotsretval-1}

\foreach [count=\i,evaluate=\i as \ylevel using \i*\yscale] \row in {0,...,\M}{

% get entries from table row
\pgfplotstablegetelem{\row}{[index]0}\of\sortedtable
\xdef\txt{\pgfplotsretval}
\pgfplotstablegetelem{\row}{[index]1}\of\sortedtable
\xdef\xstart{\pgfplotsretval}
\pgfplotstablegetelem{\row}{[index]2}\of\sortedtable
\xdef\xend{\pgfplotsretval}
\pgfplotstablegetelem{\row}{[index]3}\of\sortedtable
\xdef\barcolor{\pgfplotsretval}
\xdef\TheLastY{\ylevel}

\ifnum \xend=-1
  % single day entry, draw circle
  \filldraw [draw=black!99!\barcolor,fill=\barcolor] (\xstart*\yearscale,-\ylevel) circle[radius=\barheight/2.5] node[black,right=3pt,font=\scriptsize] {\txt};
\else
  % interval, draw a rectangle
  \fill [\barcolor] (\xstart*\yearscale,-\ylevel-\barheight/2) rectangle (\xend*\yearscale,-\ylevel+\barheight/2);
   % add text label right of the rectangle
  \node [right,font=\scriptsize] at (\xend*\yearscale,-\ylevel) {\txt};
\fi
}

\draw [Stealth-Stealth] (1500*\yearscale,0) -- (1500*\yearscale,-\TheLastY-\yscale) -- (1900*\yearscale,-\TheLastY-\yscale);

% add ticks on x-axis
\foreach \year in {1500,1550,...,1900}
   \draw (\year*\yearscale,-\TheLastY-\yscale) ++(0,3pt) -- ++(0,-6pt) node[below] {\year};

\end{tikzpicture}

\end{document}

pgfplots

Using Jake's answer to X-Bar plot with intervall (a,b) rather than (0,a), and with a bit of help from his answer to Stacked bar-plot: display total value, here is a method using pgfplots and pgfplotstable.

enter image description here

\documentclass{article}
\usepackage{pgfplots, pgfplotstable}
\pgfplotsset{compat=1.14}
\usepackage[utf8]{inputenc}

% read in table
\pgfplotstableread[col sep=comma]{
author,startyear,endyear  
Jean Bodi,1530,1596
Jean Bénigne Bossuet,1627,1704
Richelieu,1585,1642
Louis XIV,1638,1715
Thomas Hobbes,1588,1679
John Locke,1632,1704
Montesquieu,1689,1755
Francois Quesnay,1694,1774
Bayle,1647,1706
Voltaire,1694,1778
Frédéric II de Prusse,1712,1786
Joseph II,1706,1790
Catherine II, 1729,1796
Jean Jacques Rousseau,1712,1778
Sieyès,1748,1836
Robespierre,1758,1794
}\loadedtable
% sort by startyear
\pgfplotstablesort[sort key=startyear]\sortedtable\loadedtable


\begin{document}

\begin{tikzpicture}
\begin{axis}[
  nodes near coords xbar stacked configuration/.style={},
  nodes near coords style={font=\footnotesize},
  xbar stacked,
  xmin=1500,
  bar width=0.2cm,
  axis lines=left,
  width=\textwidth, height=7cm,
  enlarge y limits={abs=0.5},
  ytick=\empty,
]

\addplot [draw=none, forget plot] table [col sep=comma,x=startyear, y expr=-\coordindex]{\sortedtable};
\addplot +[
   nodes near coords,
   nodes near coords align={anchor=west},
   point meta=explicit symbolic] table[col sep=comma,x expr=\thisrow{endyear}-\thisrow{startyear}, y expr=-\coordindex,meta=author]{\sortedtable};
\end{axis}
\end{tikzpicture}
\end{document}

datatool + TikZ

Here is a fairly simple suggestion using TikZ in combination with datatool. It would perhaps benefit of some more careful sorting of the database, and it doesn't handle single-date entries like Saint Barthélémy 23 Aout 1572. Using pgfplotstable (cf. https://tex.stackexchange.com/a/20500/586) would let you sort by start year automatically.

enter image description here

\documentclass[border=4mm]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz,datatool,filecontents}
\usetikzlibrary{arrows.meta}

% generates data.txt
% I modified the structure a bit
\begin{filecontents*}{data.txt} 
author,startyear,endyear  
Jean Bodi,1530,1596
Jean Bénigne Bossuet,1627,1704
Richelieu,1585,1642
Louis XIV,1638,1715
Thomas Hobbes,1588,1679
John Locke,1632,1704
Montesquieu,1689,1755
Francois Quesnay,1694,1774
Bayle,1647,1706
Voltaire,1694,1778
Frédéric II de Prusse,1712,1786
Joseph II,1706,1790
Catherine II, 1729,1796
Jean Jacques Rousseau,1712,1778
Sieyès,1748,1836
Robespierre,1758,1794
\end{filecontents*}

% read text file into datatool database
\DTLloaddb[noheader=false]{authors}{data.txt}
\begin{document}
\begin{tikzpicture}[yscale=0.5]
% macros for convenience
\pgfmathsetmacro\yearscale{0.05} % xscale=0.05 might on second thought be easier
\pgfmathsetmacro\barheight{0.6}

% loop over database
\DTLforeach*{authors}{\txt=author,\xstart=startyear,\xend=endyear}{%
% draw a rectangle
% the DTLrowi counter is the row number of the database
\fill [blue!30] (\xstart*\yearscale,-\value{DTLrowi}-\barheight/2) rectangle (\xend*\yearscale,-\value{DTLrowi}+\barheight/2);
% add text label right of the rectangle
\node [right] at (\xend*\yearscale,-\value{DTLrowi}) {\txt};
}
% save number of rows in database to \TheBottom
\DTLsavelastrowcount{\TheBottom}

% draw an axis
\draw [Stealth-Stealth] (1500*\yearscale,0) -- (1500*\yearscale,-\TheBottom-1) -- (1900*\yearscale,-\TheBottom-1);

% add ticks on x-axis
\foreach \year in {1500,1550,...,1900}
   \draw (\year*\yearscale,-\TheBottom-1) ++(0,3pt) -- ++(0,-6pt) node[below] {\year};
\end{tikzpicture}
\end{document}
  • Thanks a lot, for the solution and for the comments. I will try to tweak it a little bit to get what I want. I will put the events in another file then add them in another color, seems easier to me than adding a condition based on the nature of the input that would be another column in my file. I also think I will add the one date events by hand – Anthony Martin Jan 19 '17 at 14:07
  • @Aerandal Ah, you wanted both in the same plot of course, sorry, that didn't occur to me. If you want all of them sorted (as in your example with the British prime ministers), I think it would probably be easiest to add a fourth column with the color information. Or, you could have pgfplotstable do that probably, I'll see if I can work something out. Will ping you again if I come up with something. – Torbjørn T. Jan 19 '17 at 22:33
  • I have managed to have both at the same time with two datasets, and two \thebottom. It is probably not the prettiest code but it works. I am wondering if I want them sorted, not sure yet. If you are willing to spend some time on that, I would rather have some kind of solution for including an event that is just a specific date, like Saint Barthélémy , 23 Aout 1572 , , for what I have less idea how to include an if loop. But you have already been very helpful ! – Anthony Martin Jan 20 '17 at 10:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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