10
$\begingroup$

This text file logs the time that a process (identified by a number) changes state ("Brown", "Blue" etc.")

2014-08-29 03:59:52 , 27273 , Brown
2014-08-29 03:59:53 , 27276 , Green
2014-08-29 03:59:55 , 27276 , Brown
2014-08-29 03:59:57 , 27303 , Red
2014-08-29 03:59:58 , 27303 , Green
2014-08-29 03:59:59 , 27303 , Brown
2014-08-29 04:00:04 , 27317 , Brown
2014-08-29 04:00:07 , 27331 , Blue
2014-08-29 04:00:07 , 27334 , Blue
2014-08-29 04:00:08 , 27331 , Red
2014-08-29 04:00:08 , 27334 , Cyan

What I try to do is to plot horizontal bars as time intervals, colored according to the third column, where x-axis is time, y-axis is process id number. One of the colors (probably Cyan) should not be displayed, as it marks the interval end.

It is actually a timeline of many parallel events.

DatePlot does not seem to help. Any suggestions?

$\endgroup$
0

3 Answers 3

10
$\begingroup$
dat = "2014-08-29 03:59:52 27273  Brown
       2014-08-29 03:59:53  27276  Green
       2014-08-29 03:59:55  27276  Brown
       2014-08-29 03:59:57  27303  Red
       2014-08-29 03:59:58  27303  Green
       2014-08-29 03:59:59  27303  Brown
       2014-08-29 04:00:04  27317  Brown
       2014-08-29 04:00:07  27331  Blue
       2014-08-29 04:00:07  27334  Blue
       2014-08-29 04:00:08  27331  Red
       2014-08-29 04:00:08  27334  Cyan";
 inputdata = ImportString[dat];

DateListPlot

ClearAll[dateListBars];
dateListBars[inpdata_, leftpadding_, rightpadding_, 
  opts : OptionsPattern[]] := 
 Module[{datasets, dates, firstdate, lastdate,
   labels, colors, gdt, dlPltF, options,
   data = {#3, DateList[#1 <> " " <> #2], ToExpression@#4} & @@@ 
     inpdata},
  gdt = GatherBy[data, First];
  {labels, colors} = Transpose[{#[[1, 1]], #[[All, 3]]} & /@ gdt];
  datasets = {#[[1, 1]], AbsoluteTime /@ #[[All, 2]], #[[All, 3]]} & /@
     gdt;
  dates = DeleteDuplicates@data[[All, 2]];
  {firstdate, lastdate} = DateList /@ ({leftpadding, rightpadding} +
      Through[{Min, Max}[AbsoluteTime /@ dates]]);
  dlPltF := DateListPlot[Thread[{{firstdate, lastdate}, #2[[1]]}],
     Joined -> True, Mesh -> {#[[2]]},
     MeshShading -> {White, Sequence @@ #[[3]], White},
     BaseStyle -> Directive[Thickness[.075], CapForm["Butt"]],
     Frame -> True, MeshStyle -> Opacity[0]] &;
  options = {PlotRange -> All, 
    GridLines -> {AbsoluteTime /@ dates, None},
    Method -> {"GridLinesInFront" -> True},
    FrameTicks -> {{Thread[{Range[Length@datasets], labels}], None},
      {{AbsoluteTime@#, Rotate[DateString[#,
            {"Hour", ":", "Minute", ":", "Second"}], Pi/2]} & /@
        {firstdate, Sequence @@ dates, lastdate}, None}},
    PlotRangePadding -> {{.5, .5}, {.5, .5}}};
  Show[MapIndexed[dlPltF, datasets], Sequence @@ options, opts]]


dateListBars[inputdata, -1, 5, ImageSize -> 600, LabelStyle -> 16] /. Cyan -> White

enter image description here

BarChart

Data preparation:

data = {#3, DateList[#1 <> " " <> #2], ToExpression@#4} & @@@ ImportString[dat];
{labels, colors} =  Transpose[{#[[1, 1]], #[[All, 3]]} & /@ GatherBy[data, First]];
datasets = {#[[1,1]], AbsoluteTime /@ #[[All, 2]], #[[All, 3]]} & /@ GatherBy[data, First];
dates = DeleteDuplicates@data[[All, 2]];
{leftpadding, rightpadding} = {-1, 5};
{firstdate, lastdate} = DateList /@ ({leftpadding, rightpadding} +
                                      Through[{Min, Max}[AbsoluteTime /@ dates]]);
bcheights = 
  DateDifference[DateList[#1], DateList[#2], "Second"][[1]] & @@@ 
     Partition[#, 2, 
      1] & /@ (Append[Prepend[#, AbsoluteTime[firstdate]], 
       AbsoluteTime[lastdate]] & /@ datasets[[All, 2]] );
bccolors = Prepend[#, White] & /@ colors;
bcdata = Thread[Style[#, #2]] & @@@ Transpose[{bcheights, bccolors}];

Handling date ticks:

bcticks = Union[Flatten[Accumulate@# & /@ bcheights]];
bcticks = Thread[{bcticks, Rotate[DateString[
        DatePlus[firstdate, {#, "Second"}],
        {"Hour", ":", "Minute", ":", "Second"}], Pi/2] & /@
     Union[Flatten[Accumulate@# & /@ bcheights]]}];

and the options

bcoptions = {ChartLayout -> "Stacked", BarOrigin -> Left,
   ChartLabels -> {Placed[labels, Axis], None},
   ChartBaseStyle -> Directive[Opacity[1], EdgeForm[]], 
   LabelStyle -> 16,
   Frame -> {{False, True}, {True, True}},
   FrameTicks -> {{None, None}, {bcticks, None}},
   GridLines -> {bcticks[[All, 1]], None}, 
   Method -> {"GridLinesInFront" -> True}, ImageSize -> 600};


 BarChart[bcdata, bcoptions] /. Cyan -> White

enter image description here

BulletGauge

bgaugedata = 
  Transpose[{Accumulate /@ bcheights, Prepend[#, White] & /@ colors, 
    labels}];
Panel[Column[
   Reverse[BulletGauge[0, foo, Append[Prepend[#1 + 5, 0], 25],
         ScaleRangeStyle -> Thread[{#2, White}], GaugeMarkers -> None,
         GaugeLabels -> 
          Placed[Style[#3, "Subsubsection"], {2, Bottom}],
         ImageSize -> 600, Axes -> False, Frame -> False, 
         TicksStyle -> Opacity[0], ReferenceMarkerStyle -> Opacity[0],
         AspectRatio -> 1/10] & @@ # & /@ bgaugedata], 
   Spacings -> -2]] /. Cyan -> White

enter image description here

TODO: Date ticks ...

$\endgroup$
1
  • 1
    $\begingroup$ wow...this beautiful+1 $\endgroup$
    – ubpdqn
    Commented Sep 2, 2014 at 8:32
8
$\begingroup$
dat = "2014-08-29 03:59:52 27273  Brown
  2014-08-29 03:59:53  27276  Green
  2014-08-29 03:59:55  27276  Brown
  2014-08-29 03:59:57  27303  Red
  2014-08-29 03:59:58  27303  Green
  2014-08-29 03:59:59  27303  Brown
  2014-08-29 04:00:04  27317  Brown
  2014-08-29 04:00:07  27331  Blue
  2014-08-29 04:00:07  27334  Blue
  2014-08-29 04:00:08  27331  Red
  2014-08-29 04:00:08  27334  Cyan";
data = {DateList[#1 <> " " <> #2], #3, #4} & @@@ ImportString[dat];
{dates, val, col} = Transpose[data];
dlp = DateListPlot[MapThread[{{#1, #2}, {Last@dates, #2}} &, {Most@dates, Most@val}], 
     ImageSize -> 500, 
     PlotStyle -> (Thread[{Thickness[0.01],Most@(ToExpression /@ col)}]), PlotLegends ->    (Most@val), 
  FrameTicks -> {Automatic, None}]

enter image description here

Note if, as the question suggest, the "values" are labels and the bars are desired to be equally spaced this could be done using MapIndexed rather than MapThread

$\endgroup$
5
  • $\begingroup$ Oooh right. Now I see what the OP meant :) $\endgroup$
    – Öskå
    Commented Sep 1, 2014 at 10:59
  • $\begingroup$ @Öskå happens to us all :) $\endgroup$
    – ubpdqn
    Commented Sep 1, 2014 at 11:14
  • $\begingroup$ @Öskå in the OP's question he specifically notes the last entry is end of interval and Cyan will not be needed...hence Most and no Cyan. $\endgroup$
    – ubpdqn
    Commented Sep 1, 2014 at 11:17
  • $\begingroup$ Thanks very much. I had to do some changes on the code, namely erased the "PlotLegends" and the "ImportString". $\endgroup$
    – user32916
    Commented Sep 2, 2014 at 11:13
  • $\begingroup$ @user32916 I had changed your original data (omitting commas). kguler has posted a much better answer than mine $\endgroup$
    – ubpdqn
    Commented Sep 2, 2014 at 11:27
2
$\begingroup$

With se.dat being exactly what you provided:

dat = StringSplit[#, ","] & /@ Import["~/se.dat", "List"];
dates = ToExpression /@ 
          (StringSplit[#, ","] & /@ 
            (StringReplace[StringTrim@#, {"-" | " " | ":" -> ","}] & /@ First /@ dat))
val = ToExpression[#[[2]]] & /@ dat
col = ToExpression[#[[3]]] & /@ dat
DateListPlot[List /@ Thread@{dates, val}, PlotStyle -> col]

Mathematica graphics

$\endgroup$
0

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.