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.

For reasons too lengthy to explain, I would like to display a list of dates or years (as numbers or strings) as FrameTicks on a ListLinePlot.

An example of what I have so far follows:

xle = FinancialData["XLE", All];
DateListPlot[xle, ImageSize -> 350]
ListLinePlot[xle[[All, 2]], ImageSize -> 350]
firstDateByYear = First /@ SplitBy[xle[[All, 1]], #[[1]] &]
positions = Flatten[Position[xle[[All, 1]], #] & /@ firstDateByYear]
years= firstDateByYear[[All,1]]

Plots

{{1998, 12, 22}, {1999, 1, 4}, {2000, 1, 3}, {2001, 1, 2}, {2002, 1, 2},{2003, 1, 2}, {2004, 1, 2}, {2005, 1, 3}, {2006, 1, 3}, {2007, 1, 3}, {2008, 1, 2}, {2009, 1, 2}, {2010, 1, 4}, {2011, 1, 3}, {2012, 1, 3}}

{1, 8, 260, 512, 760, 1012, 1264, 1516, 1768, 2019, 2270, 2523, 2775, 3027, 3279}

{1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012}

I thought that identifying a position at which I wanted to place a label would help.

The following earlier question Formatting Ticks and FrameTicks labels with a function relates to what I want to do, but I haven't understood it sufficiently to adapt it to my needs.

Doing something like placing a string for the year at every other position in the list "positions" would give me a clear idea of how to do more complicated things on my own.

share|improve this question
add comment

2 Answers

up vote 5 down vote accepted

You got very close to the solution: you simply have to pair up the positions and the year values, and feed it to the bottom FrameTicks specification (as in FrameTicks->{{left, right}, {bottom, top}}). I've filtered the years to only display those that are multiples of 5. Note however that this method of year & position extraction works only if the curated financial data is continuous (i.e. there are no gaps of date).

xle = FinancialData["XLE", All];

years = xle[[All, 1, 1]];
pos = Flatten[Position[years, #, 1, 1] & /@ Union@years];
ticks = Thread@{pos, Union@years};
filteredTicks = Cases[ticks, _?(Mod[Last@#, 5] == 0 &)];

DateListPlot[xle, ImageSize -> 350]
ListLinePlot[xle[[All, 2]], ImageSize -> 350, Frame -> True, 
 Axes -> False, 
 FrameTicks -> {{Automatic, Automatic}, {filteredTicks, None}}]

Mathematica graphics

share|improve this answer
    
Thanks for the quick solution and insights into uses of Union and Thread I don't usually think about. –  Jagra Jun 28 '12 at 19:07
add comment

Firstly using ListLinePlot instead of DateListPlot is a good choice. You will find it much faster.

xle = FinancialData["XLE", All];

AbsoluteTiming[DateListPlot[xle, ImageSize -> 350];]
{0.438556, Null}

AbsoluteTiming[ListLinePlot[xle[[All, 2]], ImageSize -> 350];]
{0.021308, Null}

So 20 times faster but of course you need to process the ticks. For regular data István Zachar's solution will be fastest. On my machine 0.027.

For irregular data you will need to work with AbsoluteTimes. Incidentally you will find DateListPlot works faster if you first convert to AbsoluteTime (even taking into account the time taken for this conversion). Typically rendering time will be halved.

So the method below will work for irregular intervals and is still about 5 times faster than DateListPlot (on my machine).

AbsoluteTiming[
 xle1 = xle;
 xle1[[All, 1]] = AbsoluteTime /@ xle[[All, 1]];
 years = Range[xle[[1, 1, 1]], xle[[-1, 1, 1]]];
 absYears = AbsoluteTime /@ Thread[{years, 1, 1}];
 interval = 5;
 selector = Boole[Thread[Mod[years, interval] == 0]];
 ticks = DeleteCases[
   Transpose[{selector*absYears, selector*years}], {0, 0}];

(* or if you minor ticks then uncomment this
ticks = Transpose[{absYears, selector*years}] /. 0 -> ""; *)

 ListLinePlot[xle1, ImageSize -> 350, Frame -> True, Axes -> False, 
  FrameTicks -> {{Automatic, Automatic}, {ticks, None}}]]

{0.08415, Null}

Incidentally I use ListLinePlot for dynamic plotting such as this

enter image description here

because it updates much faster than DateListPlot.

share|improve this answer
    
I hadn't thought about the timing issue. Very helpful insight. Thx –  Jagra Jun 29 '12 at 15:21
    
No worries. Note that for financial data you will need to use this approach if you want accurate ticks because exchanges are not open on new years day. –  Mike Honeychurch Jun 29 '12 at 22:15
add comment

Your Answer

 
discard

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

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