<a href="http://code.google.com/p/dygraphs/">code.google.com/p/dygraphs</a></p>
</center>
-<p>The dygraphs JavaScript library produces produces interactive, zoomable charts of time series based on CSV files.</p>
+<p>The dygraphs JavaScript library produces produces interactive, zoomable charts of time series.</p>
<h3>Features</h3>
<ul>
<li>Interactive zoom</li>
<li>Adjustable averaging period</li>
<li>Customizable click-through actions</li>
+ <li>Compatible with the Google Visualization API</li>
</ul>
<h3>Caveats</h3>
"rgb(255,100,100)",
"#00DD55",
"rgba(50,50,200,0.4)"],
- padding: {left: 40, right: 30, top: 15, bottom: 15}
+ padding: {left: 40, right: 30, top: 15, bottom: 15},
}
);
</script>
+<p>For more demos, browse the dygraph <a href="tests/">tests</a> directory.</p>
+
<h2>Usage</h2>
-<p>The DateGraph library depends on two other JS libraries: <a href="http://www.mochikit.com/">MochiKit</a> and <a href="http://www.liquidx.net/plotkit/">PlotKit</a>. Rather than tracking down copies of these libraries, I recommend using a packed version of dygraphs that combines all three libraries into a single JS file. Either grab this file from dygraph project's <a href="http://code.google.com/p/dygraphs/downloads/list">downloads</a> page or create it yourself by <a href="http://code.google.com/p/dygraphs/source/checkout">checking out</a> a copy of the code and running:
+<p>The dygraphs library depends on two other JS libraries: <a href="http://www.mochikit.com/">MochiKit</a> and <a href="http://www.liquidx.net/plotkit/">PlotKit</a>. Rather than tracking down copies of these libraries, I recommend using a packed version of dygraphs that combines all three libraries into a single JS file. Either grab this file from dygraph project's <a href="http://code.google.com/p/dygraphs/downloads/list">downloads</a> page or create it yourself by <a href="http://code.google.com/p/dygraphs/source/checkout">checking out</a> a copy of the code and running:
<pre>./generate-combined.sh</pre>
<script type="text/javascript" src="combined.js"></script>
</head>
<body>
-<div id="graphdiv" style="width:400px; height:300px;"></div>
+<div id="graphdiv"></div>
<script type="text/javascript">
- g = new DateGraph(
+ g = new Dygraph(
document.getElementById("graphdiv"), // containing div
- function() { // function or path to CSV file.
- return "20080507,75\n" +
- "20080508,70\n" +
- "20080509,80\n";
- },
- [ "Temperature" ], // names of data series
- {} // additional options (see below)
+ "Date,Temperature\n" + // CSV or path to a CSV file.
+ "20080507,75\n" +
+ "20080508,70\n" +
+ "20080509,80\n",
);
</script>
</body>
</html>
</pre>
</td><td valign=top>
- <div id="graphdiv" style="width:400px; height:300px;"></div>
+ <div id="graphdiv"></div>
<script type="text/javascript">
- g = new DateGraph(
- document.getElementById("graphdiv"),
- function() { // function or path to CSV file.
- return "20080507,75\n" +
- "20080508,70\n" +
- "20080509,80\n";
- },
- [ "Temperature" ], // names of data series
- {} // additional options
- );
+ g = new Dygraph(
+ document.getElementById("graphdiv"), // containing div
+ "Date,Temperature\n" + // CSV or path to a CSV file.
+ "20080507,75\n" +
+ "20080508,70\n" +
+ "20080509,80\n"
+ );
</script>
</td></tr></table>
-<p>In order to keep this example self-contained, the second parameter is a function that returns CSV data. These lines <i>must</i> begin with a date in the form <i>YYYYMMDD</i>. In most applications, it makes more sense to include a CSV file instead. If the second parameter to the constructor is a string, it will be interpreted as the path to a CSV file. The DateGraph will perform an XMLHttpRequest to retrieve this file and display the data when it becomes available. Make sure your CSV file is readable and serving from a place that understands XMLHttpRequest's! In particular, you cannot specify a CSV file using <code>"file:///"</code>. Here's an example: (data from <a href="http://www.wunderground.com/history/airport/KNUQ/2007/1/1/CustomHistory.html?dayend=31&monthend=12&yearend=2007&req_city=NA&req_state=NA&req_statename=NA">Weather Underground</a>)</p>
+<p>In order to keep this example self-contained, the second parameter is a function that returns CSV data. These lines <i>must</i> begin with a date in the form <i>YYYYMMDD</i>. In most applications, it makes more sense to include a CSV file instead. If the second parameter to the constructor is a string, it will be interpreted as the path to a CSV file. The Dygraph will perform an XMLHttpRequest to retrieve this file and display the data when it becomes available. Make sure your CSV file is readable and serving from a place that understands XMLHttpRequest's! In particular, you cannot specify a CSV file using <code>"file:///"</code>. Here's an example: (data from <a href="http://www.wunderground.com/history/airport/KNUQ/2007/1/1/CustomHistory.html?dayend=31&monthend=12&yearend=2007&req_city=NA&req_state=NA&req_statename=NA">Weather Underground</a>)</p>
<table>
<tr><th>HTML</th>
<body>
<div id="graphdiv" style="width:600px; height:300px;"></div>
<script type="text/javascript">
- g = new DateGraph(
+ g = new Dygraph(
document.getElementById("graphdiv"),
"temperatures.csv", // path to CSV file
- null, // labels in top line of CSV file
- {}
+ {} // additional options
);
</script>
</body>
</td><td valign=top>
<div id="graphdiv2" style="width:600px; height:300px;"></div>
<script type="text/javascript">
- g2 = new DateGraph(
+ g2 = new Dygraph(
document.getElementById("graphdiv2"),
- "temperatures.csv", null, {}
+ "temperatures.csv", {}
);
</script>
</td></tr></table>
<p>Click <a href="temperatures.csv">here</a> to view the <code>temperatures.csv</code> file. There are a few things to note here:</p>
<ul>
- <li>Because the third parameter to the DateGraph constructor was <code>null</code>, the labels were taken from the first line of the data instead. The first line of <code>temperatures.csv</code> is <code>Date,High,Low</code>.</li>
- <li>DateGraph automatically chose two different, easily-distinguishable colors for the two data series.</li>
+ <li>The Dygraph sent off an XHR to get the temperatures.csv file.</li>
+ <li>The labels were taken from the first line of <code>temperatures.csv</code>, which is <code>Date,High,Low</code>.</li>
+ <li>The Dygraph automatically chose two different, easily-distinguishable colors for the two data series.</li>
<li>The labels on the x-axis have switched from days to months. If you zoom in, they'll switch to weeks and then days.</li>
- <li>Some heuristics are used to determine a good vertical range for the data. The idea is to make all the data visible and have human-friendly values on the axis (i.e. 200 instead of 193.4). Generally this works well, but in this case the vertical range is way too large.</li>
+ <li>Some heuristics are used to determine a good vertical range for the data. The idea is to make all the data visible and have human-friendly values on the axis (i.e. 200 instead of 193.4). Generally this works well.</li>
<li>The data is very spiky. A moving average would be easier to interpret.</li>
</ul>
-<p>These last two problems can be fixed by specifying the appropriate options in the fourth parameter to the DateGraph constructor. To set the number of days for a moving average, use the <b>rollPeriod</b> option. To set the range of the y-axis, use the <b>valueRange</b> option. Here's how it's done:</p>
+<p>This problem can be fixed by specifying the appropriate options in the "additional options" parameter to the Dygraph constructor. To set the number of days for a moving average, use the <b>rollPeriod</b> option. Here's how it's done:</p>
<table>
<tr><th>HTML</th>
<body>
<div id="graphdiv" style="width:600px; height:300px;"></div>
<script type="text/javascript">
- g = new DateGraph(
+ g = new Dygraph(
document.getElementById("graphdiv"),
- "temperatures.csv", null,
+ "temperatures.csv",
{ rollPeriod: 7,
showRoller: true,
- valueRange: [25, 100]
}
);
</script>
</td><td valign=top>
<div id="graphdiv3" style="width:600px; height:300px;"></div>
<script type="text/javascript">
- g3 = new DateGraph(
+ g3 = new Dygraph(
document.getElementById("graphdiv3"),
- "temperatures.csv", null,
+ "temperatures.csv",
{ rollPeriod: 7,
showRoller: true,
- valueRange: [25, 100]
}
);
</script>
<p>A rolling average can be set using the text box in the lower left-hand corner of the graph (the showRoller attribute is what makes this appear).</p>
<h2>Error Bars</h2>
-<p>Another significant feature of the dygraphs library is the ability to display error bars around data series. One standard deviation must be specified for each data point. A +/-<i>n</i> sigma band will be drawn around the data series at that point. If a moving average is being displayed, DateGraph will compute the standard deviation of the average at each point. (i.e. <i>σ</i> = sqrt((<i>σ_1</i>^2 + <i>σ_2</i>^2 + ... + <i>σ_n</i>^2)/<i>n</i>))</p>
+<p>Another significant feature of the dygraphs library is the ability to display error bars around data series. One standard deviation must be specified for each data point. A +/-<i>n</i> sigma band will be drawn around the data series at that point. If a moving average is being displayed, dygraphs will compute the standard deviation of the average at each point. (i.e. <i>σ</i> = sqrt((<i>σ_1</i>^2 + <i>σ_2</i>^2 + ... + <i>σ_n</i>^2)/<i>n</i>))</p>
<p>Here's a demonstration. There are two data series. One is <code>N(100,10)</code> with a standard deviation of 10 specified at each point. The other is <code>N(80,20)</code> with a standard deviation of 20 specified at each point. The CSV file was generated using Octave and can be viewed <a href="twonormals.csv">here</a>.</p>
></div>
<script type="text/javascript">
$ = document.getElementById;
-g = new DateGraph(
+g = new Dygraph(
$("graphdiv"),
"twonormals.csv",
- null,
{ rollPeriod: 7,
showRoller: true,
errorBars: true,
<div id="graphdiv4" style="width:800px; height:400px;"></div>
<script type="text/javascript">
$ = document.getElementById;
-new DateGraph(
+new Dygraph(
document.getElementById("graphdiv4"),
"twonormals.csv",
- null,
{ rollPeriod: 14,
showRoller: true,
errorBars: true,
<div id=dow_chart style="width:1000px; height:400px;"></div>
<script type="text/javascript">
// From http://www.econstats.com/eqty/eq_d_mi_3.csv
- dow = new DateGraph(
+ dow = new Dygraph(
document.getElementById('dow_chart'),
"dow.txt",
- null,
{
showRoller: true,
customBars: true,
padding: {left:30, right:30, top:5, bottom:5}
});
</script>
+<!--
+
+Here is a script to regenerate the Dow Jones plot:
+
+# Get unadjusted DJIA data in a nice format:
+curl -O http://www.econstats.com/eqty/eq_d_mi_3.csv
+sed '1,17d' eq_d_mi_3.csv | cut -d, -f1,6 | perl -pe 's/(\d{4}-\d\d)-\d\d/$1/g' | perl -pe 's/, */\t/' | grep -v 'na' | perl -ne 'chomp; ($m,$v) = split/\t/; $close{$m} = $v; if ($low{$m} == 0 || $v < $low{$m}) { $low{$m}=$v } if ($v > $high{$m}) { $high{$m} = $v } END { for $x(sort keys %close) { print "$x\t$low{$x}\t$close{$x}\t$high{$x}\n" } } ' > monthly-djia.tsv
+
+# Fetch and format the CPI data:
+curl 'http://data.bls.gov/PDQ/servlet/SurveyOutputServlet?series_id=CUUR0000SA0&years_option=all_years&periods_option=all_periods&output_type=column&output_format=text&delimiter=comma' > cpi-u.txt
+sed '1,/Series Id,Year,/d' cpi-u.txt | sed '/^$/,$d' | cut -d, -f2,3,4 | perl -ne 'print if /,M(0[0-9]|1[012]),/' | perl -pe 's/(\d{4}),M(\d{2}),/$1-$2\t/g' > cpi-u.tsv
+
+# Merge:
+join -t' ' cpi-u.tsv monthly-djia.tsv > annotated-djia.tsv
+perl -ne 'BEGIN{print "Month,Nominal,Real\n"} chomp; ($m,$cpi,$low,$close,$high) = split /\t/; $cpi /= 100.0; print "$m-15,$low;$close;$high,",($low/$cpi),";",($close/$cpi),";",($high/$cpi),"\n"' annotated-djia.tsv > dow.txt
+
+-->
<h2>Other Options</h2>
-<p>These are the options that can be passed in through the fourth parameter of the DateGraph constructor.</p>
+<p>These are the options that can be passed in through the optional third parameter of the Dygraph constructor. To see demonstrations of many of these options, browse the <a href="tests/">dygraphs tests</a> directory.</p>
<table class=thinborder width=1000>
<tr><th>Name</th><th>Sample Value</th><th>Description</th></tr>
<tr>
+ <td><b>includeZero</b></td>
+ <td><code>true, false</code></td>
+ <td>Usually, dygraphs will use the range of the data plus some padding to
+ set the range of the y-axis. If this option is set, the y-axis will always
+ include zero, typically as the lowest value. This can be used to avoid
+ exaggerating the variance in the data.</td>
+ </tr>
+
+ <tr>
<td><b>rollPeriod</b></td>
<td><code>7</code></td>
<td>Number of days over which to average data. Discussed extensively above.</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>showRoller</b></td>
<td><code>true</code></td>
<td>Should the rolling average period text box be shown? Default is false.</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>colors</b></td>
<td><code>['red', '#00FF00']</code></td>
<td>List of colors for the data series. These can be of the form "#AABBCC"
or "rgb(255,100,200)" or "yellow", etc. If not specified, equally-spaced
points around a color wheel are used.</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>colorSaturation</b></td>
<td><code>1.0</code></td>
<td>If <b>colors</b> is not specified, saturation of the
automatically-generated data series colors. (0.0-1.0, default:
1.0)</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>colorValue</b></td>
<td><code>0.5</code></td>
<td>If colors is not specified, value of the data series colors, as in
hue/saturation/value. (0.0-1.0, default 0.5)</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>clickCallback</b></td>
<td><code>function(e,date){ alert(date); }</code></td>
<td>A function to call when a data point is clicked. The function should take
two arguments, the event object for the click and the date that was
clicked. (default null)</td>
- </tr><tr>
- <td><b>errorBars</b></td>
- <td><code>false</code></td>
- <td>Does the data contain standard deviations? Setting this to true alters
- the input format (see above). (default false)</td>
- </tr><tr>
+ </tr>
+
+ <tr>
+ <td><b>zoomCallback</b></td>
+ <td><code>function(minDate,maxDate) {}</code></td>
+ <td>A function to call when the zoom window is changed (either by zooming
+ in or out). minDate and maxDate are millis since epoch.</td>
+ </tr>
+
+ <tr>
<td><b>strokeWidth</b></td>
<td><code>2.0</code></td>
<td>Width of the data lines. This can be used to increase the contrast or
some graphs. (default 1.0)</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>dateWindow</b></td>
- <td><code>[(new Date('2006-01-01')).valueOf(),<br/>
+ <td><code>[Date.parse('2006-01-01'),<br/>
(new Date()).valueOf()]</code></td>
<td>Initially zoom in on a section of the graph. Is of the form [earliest,
latest], where earliest/latest are millis since epoch. By default, the
full range of the input is shown.</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>valueRange</b></td>
<td><code>[10, 110]</code></td>
<td>Explicitly set the vertical range of the graph to [low, high]. By
default, some clever heuristics are used (see above).</td>
- </tr><tr>
- <td><b>minTickSize</b></td>
- <td><code>1</code</td>
- <td>The difference between ticks on the y-axis can be greater than or equal
- to this, but no less. If you set it to 1, for instance, you'll never get
- nonintegral gaps between ticks.</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>labelsSeparateLines</b></td>
<td><code>true</code></td>
<td>Put <br/> between lines in the label string. Often used in
conjunction with <b>labelsDiv</b>. (default false)</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>labelsDiv</b></td>
<td><code>document.getElementById('foo')</code></td>
<td>Show data labels in an external div, rather than on the graph. (default
null)</td>
- </tr><tr>
+ </tr>
+
+ <tr>
<td><b>labelsKMB</b></td>
<td><code>true</code></td>
<td>Show K/M/B for thousands/millions/billions on y-axis (default
false).</td>
</tr>
+
+ <tr>
+ <td><b>labelsDivWidth</b></td>
+ <td>250</td>
+ <td>Width (in pixels) of the div which shows information on the
+ currently-highlighted points.</td>
+ </tr>
+
+ <tr>
+ <td><b>labelsDivStyles</b></td>
+ <td>{}</td>
+ <td>Additional styles to apply to the currently-highlighted points div. For
+ example, { 'font-weigth': 'bold' } will make the labels bold.</td>
+ </tr>
+
+ <tr>
+ <td><b>highlightCircleSize</b></td>
+ <td><code>3</code></td>
+ <td>Size (in pixels) of the dot drawn over highlighted points (default 3).</td>
+ </tr>
+
+ <tr>
+ <td><b>drawPoints</b></td>
+ <td><code>false</code></td>
+ <td>Draw a small dot at each point, in addition to a line going through
+ the point. This makes the individual data points easier to see, but can
+ increase visual clutter in the chart. Default: false</td>
+ </tr>
+
+ <tr>
+ <td><b>pointSize</b></td>
+ <td><code>1.0</code></td>
+ <td>The size of the dot to draw on each point in pixels (see
+ drawPoints). A dot is always drawn when a point is "isolated", i.e.
+ there is a missing point on either side of it. This also controls the
+ size of those dots.</td>
+ </tr>
+
+ <tr>
+ <td><b>pixelsPerXLabel</b>, <b>pixelsPerYLabel</b></td>
+ <td>50</td>
+ <td>Number of pixels to require between each x- and y-label. Larger values
+ will yield a sparser axis with fewer ticks. Defaults: 60 (x-axis), 30
+ (y-axis).</td>
+ </tr>
+
+ <tr>
+ <td><b>xAxisLabelWidth</b>, <b>yAxisLabelWidth</b></td>
+ <td>50</td>
+ <td>Width (in pixels) of the x- and y-axis labels.</td>
+ </tr>
+
+ <tr>
+ <td><b>axisLabelFontSize</b></td>
+ <td>14</td>
+ <td>Size of the font (in pixels) to use in the axis labels, both x- and
+ y-axis.</td>
+ </tr>
+
<tr>
- <td><b>padding</b></td>
- <td><code>{left: 40, right: 30,<br/>top: 5,
- bottom: 15}</code></td>
- <td>Adds extra pixels of padding around the graph. Sometimes a dygraph
- gets clipped by surrounding text (see the Demo at the top of this page).
- Setting this property appropriately will fix this problem.</td>
+ <td><b>rightGap</b></td>
+ <td>5</td>
+ <td>Number of pixels to leave blank at the right edge of the Dygraph. This
+ makes it easier to highlight the right-most data point.</td>
+ </tr>
+
+ <tr>
+ <td><b>errorBars</b></td>
+ <td><code>false</code></td>
+ <td>Does the data contain standard deviations? Setting this to true alters
+ the input format (see above). (default false)</td>
+ </tr>
+
+ <tr>
+ <td><b>sigma</b></td>
+ <td>2</td>
+ <td>When errorBars is set, shade this many standard deviations above/below
+ each point.</td>
+ </tr>
+
+ <tr>
+ <td><b>fractions</b></td>
+ <td>false</td>
+ <td>When set, attempt to parse each cell in the CSV file as "a/b", where a
+ and b are integers. The ratio will be plotted. This allows computation of
+ Wilson confidence intervals (see below).</td>
+ </tr>
+
+ <tr>
+ <td><b>wilsonInterval</b></td>
+ <td>true</td>
+ <td>Use in conjunction with the "fractions" option. Instead of plotting +/-
+ N standard deviations, dygraphs will compute a Wilson confidence interval
+ and plot that. This has more reasonable behavior for ratios close to 0 or
+ 1.</td>
+ </tr>
+
+ <tr>
+ <td><b>customBars</b></td>
+ <td>false</td>
+ <td>When set, parse each CSV cell as "low;middle;high". Error bars will be
+ drawn for each point between low and high, with the series itself going
+ through middle.</td>
</tr>
</table>
-<p>Any options you specify also get passed on to PlotKit's <a href="http://media.liquidx.net/js/plotkit-doc/PlotKit.Renderer.html">Renderer</a> class. DateGraph will override some of these (e.g. strokeColor), but others may be useful. The <code>padding</code> property is an example of this.</p>
+<p>Any options you specify also get passed on to PlotKit's <a href="http://media.liquidx.net/js/plotkit-doc/PlotKit.Renderer.html">Renderer</a> class. dygraphs will override some of these (e.g. strokeColor), but others may be useful. The <code>padding</code> property is an example of this.</p>
<h2>Common Gotchas</h2>
<p>Here are a few problems that I've frequently run into while using the
href="http://www.getfirebug.com/">Firebug</a>.</li>
<li>Make sure your CSV files are in the correct format. They must be of the
- form <code>YYYYMMDD,series1,series2,...</code>. If you're specifying the
- names of each data series in the CSV file itself, make sure that you pass
- <code>null</code> as the third parameter to the DateGraph constructor to let
- the library know that. And if you set the <code>errorBars</code> property,
- make sure you alternate data series and standard deviations.</li>
+ form <code>YYYYMMDD,series1,series2,...</code>. And if you set the
+ <code>errorBars</code> property, make sure you alternate data series and
+ standard deviations.</li>
<li>dygraphs are not happy when placed inside a <code><center></code>
tag. This applies to the CSS <code>text-align</code> property as well. If you
- want to center a DateGraph, put it inside a table with "align=center"
+ want to center a Dygraph, put it inside a table with "align=center"
set.</li>
- <li>If you specify the <code>colors</code> property or name the data series
- using the third parameter of the DateGraph constructor, make sure the number
- of data series agree in all places: <code>colors</code>, third parameter and
- in each line of the CSV file itself.</li>
-
<li>Don't set the <code>dateWindow</code> property to a date. It expects
milliseconds since epoch, which can be obtained from a JavaScript Date
object's valueOf method.</li>
</ul>
+<h2>Data Policy</h2>
+<p>dygraphs is purely client-side JavaScript. It does not send your data to any
+servers -- the data is processed entirely in the client's browser.</p>
+
<p><font size=-1>Created May 9, 2008 by <a href=mailto:danvdk@gmail.com>Dan Vanderkam</a></font></p>
+<!-- Google Analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+_uacct = "UA-769809-1";
+urchinTracker();
+</script>
+
</body>
</html>