選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

220 行
7.4 KiB

  1. /**
  2. * jqPlot
  3. * Pure JavaScript plotting plugin using jQuery
  4. *
  5. * Version: 1.0.0b2_r792
  6. *
  7. * Copyright (c) 2009-2011 Chris Leonello
  8. * jqPlot is currently available for use in all personal or commercial projects
  9. * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
  10. * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
  11. * choose the license that best suits your project and use it accordingly.
  12. *
  13. * Although not required, the author would appreciate an email letting him
  14. * know of any substantial use of jqPlot. You can reach the author at:
  15. * chris at jqplot dot com or see http://www.jqplot.com/info.php .
  16. *
  17. * If you are feeling kind and generous, consider supporting the project by
  18. * making a donation at: http://www.jqplot.com/donate.php .
  19. *
  20. * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
  21. *
  22. * version 2007.04.27
  23. * author Ash Searle
  24. * http://hexmen.com/blog/2007/03/printf-sprintf/
  25. * http://hexmen.com/js/sprintf.js
  26. * The author (Ash Searle) has placed this code in the public domain:
  27. * "This code is unrestricted: you are free to use it however you like."
  28. *
  29. */
  30. (function($) {
  31. /**
  32. * Class: $.jqplot.Trendline
  33. * Plugin which will automatically compute and draw trendlines for plotted data.
  34. */
  35. $.jqplot.Trendline = function() {
  36. // Group: Properties
  37. // prop: show
  38. // Wether or not to show the trend line.
  39. this.show = $.jqplot.config.enablePlugins;
  40. // prop: color
  41. // CSS color spec for the trend line.
  42. // By default this wil be the same color as the primary line.
  43. this.color = '#666666';
  44. // prop: renderer
  45. // Renderer to use to draw the trend line.
  46. // The data series that is plotted may not be rendered as a line.
  47. // Therefore, we use our own line renderer here to draw a trend line.
  48. this.renderer = new $.jqplot.LineRenderer();
  49. // prop: rendererOptions
  50. // Options to pass to the line renderer.
  51. // By default, markers are not shown on trend lines.
  52. this.rendererOptions = {marker:{show:false}};
  53. // prop: label
  54. // Label for the trend line to use in the legend.
  55. this.label = '';
  56. // prop: type
  57. // Either 'exponential', 'exp', or 'linear'.
  58. this.type = 'linear';
  59. // prop: shadow
  60. // true or false, wether or not to show the shadow.
  61. this.shadow = true;
  62. // prop: markerRenderer
  63. // Renderer to use to draw markers on the line.
  64. // I think this is wrong.
  65. this.markerRenderer = {show:false};
  66. // prop: lineWidth
  67. // Width of the trend line.
  68. this.lineWidth = 1.5;
  69. // prop: shadowAngle
  70. // Angle of the shadow on the trend line.
  71. this.shadowAngle = 45;
  72. // prop: shadowOffset
  73. // pixel offset for each stroke of the shadow.
  74. this.shadowOffset = 1.0;
  75. // prop: shadowAlpha
  76. // Alpha transparency of the shadow.
  77. this.shadowAlpha = 0.07;
  78. // prop: shadowDepth
  79. // number of strokes to make of the shadow.
  80. this.shadowDepth = 3;
  81. this.isTrendline = true;
  82. };
  83. $.jqplot.postSeriesInitHooks.push(parseTrendLineOptions);
  84. $.jqplot.postDrawSeriesHooks.push(drawTrendline);
  85. $.jqplot.addLegendRowHooks.push(addTrendlineLegend);
  86. // called witin scope of the legend object
  87. // current series passed in
  88. // must return null or an object {label:label, color:color}
  89. function addTrendlineLegend(series) {
  90. var lt = series.trendline.label.toString();
  91. var ret = null;
  92. if (this.renderer.constructor != $.jqplot.PieRenderer && series.trendline.show && lt) {
  93. ret = {label:lt, color:series.trendline.color};
  94. }
  95. return ret;
  96. }
  97. // called within scope of a series
  98. function parseTrendLineOptions (target, data, seriesDefaults, options, plot) {
  99. if (this.renderer.constructor == $.jqplot.LineRenderer) {
  100. this.trendline = new $.jqplot.Trendline();
  101. options = options || {};
  102. $.extend(true, this.trendline, {color:this.color}, seriesDefaults.trendline, options.trendline);
  103. this.trendline.renderer.init.call(this.trendline, null);
  104. }
  105. }
  106. // called within scope of series object
  107. function drawTrendline(sctx, options) {
  108. // if we have options, merge trendline options in with precedence
  109. options = $.extend(true, {}, this.trendline, options);
  110. if (options.show && this.renderer.constructor != $.jqplot.PieRenderer) {
  111. var fit;
  112. // this.renderer.setGridData.call(this);
  113. var data = options.data || this.data;
  114. fit = fitData(data, this.trendline.type);
  115. var gridData = options.gridData || this.renderer.makeGridData.call(this, fit.data);
  116. this.trendline.renderer.draw.call(this.trendline, sctx, gridData, {showLine:true, shadow:this.trendline.shadow});
  117. }
  118. }
  119. function regression(x, y, typ) {
  120. var type = (typ == null) ? 'linear' : typ;
  121. var N = x.length;
  122. var slope;
  123. var intercept;
  124. var SX = 0;
  125. var SY = 0;
  126. var SXX = 0;
  127. var SXY = 0;
  128. var SYY = 0;
  129. var Y = [];
  130. var X = [];
  131. if (type == 'linear') {
  132. X = x;
  133. Y = y;
  134. }
  135. else if (type == 'exp' || type == 'exponential') {
  136. for ( var i=0; i<y.length; i++) {
  137. // ignore points <= 0, log undefined.
  138. if (y[i] <= 0) {
  139. N--;
  140. }
  141. else {
  142. X.push(x[i]);
  143. Y.push(Math.log(y[i]));
  144. }
  145. }
  146. }
  147. for ( var i = 0; i < N; i++) {
  148. SX = SX + X[i];
  149. SY = SY + Y[i];
  150. SXY = SXY + X[i]* Y[i];
  151. SXX = SXX + X[i]* X[i];
  152. SYY = SYY + Y[i]* Y[i];
  153. }
  154. slope = (N*SXY - SX*SY)/(N*SXX - SX*SX);
  155. intercept = (SY - slope*SX)/N;
  156. return [slope, intercept];
  157. }
  158. function linearRegression(X,Y) {
  159. var ret;
  160. ret = regression(X,Y,'linear');
  161. return [ret[0],ret[1]];
  162. }
  163. function expRegression(X,Y) {
  164. var ret;
  165. var x = X;
  166. var y = Y;
  167. ret = regression(x, y,'exp');
  168. var base = Math.exp(ret[0]);
  169. var coeff = Math.exp(ret[1]);
  170. return [base, coeff];
  171. }
  172. function fitData(data, typ) {
  173. var type = (typ == null) ? 'linear' : typ;
  174. var ret;
  175. var res;
  176. var x = [];
  177. var y = [];
  178. var ypred = [];
  179. for (i=0; i<data.length; i++){
  180. if (data[i] != null && data[i][0] != null && data[i][1] != null) {
  181. x.push(data[i][0]);
  182. y.push(data[i][1]);
  183. }
  184. }
  185. if (type == 'linear') {
  186. ret = linearRegression(x,y);
  187. for ( var i=0; i<x.length; i++){
  188. res = ret[0]*x[i] + ret[1];
  189. ypred.push([x[i], res]);
  190. }
  191. }
  192. else if (type == 'exp' || type == 'exponential') {
  193. ret = expRegression(x,y);
  194. for ( var i=0; i<x.length; i++){
  195. res = ret[1]*Math.pow(ret[0],x[i]);
  196. ypred.push([x[i], res]);
  197. }
  198. }
  199. return {data: ypred, slope: ret[0], intercept: ret[1]};
  200. }
  201. })(jQuery);