1########################################################################
2##
3## Copyright (C) 2003-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn  {} {} pareto (@var{y})
28## @deftypefnx {} {} pareto (@var{y}, @var{x})
29## @deftypefnx {} {} pareto (@var{hax}, @dots{})
30## @deftypefnx {} {@var{h} =} pareto (@dots{})
31## Draw a Pareto chart.
32##
33## A Pareto chart is a bar graph that arranges information in such a way
34## that priorities for process improvement can be established; It organizes
35## and displays information to show the relative importance of data.  The chart
36## is similar to the histogram or bar chart, except that the bars are arranged
37## in decreasing magnitude from left to right along the x-axis.
38##
39## The fundamental idea (Pareto principle) behind the use of Pareto
40## diagrams is that the majority of an effect is due to a small subset of the
41## causes.  For quality improvement, the first few contributing causes
42## (leftmost bars as presented on the diagram) to a problem usually account for
43## the majority of the result.  Thus, targeting these "major causes" for
44## elimination results in the most cost-effective improvement scheme.
45##
46## Typically only the magnitude data @var{y} is present in which case
47## @var{x} is taken to be the range @code{1 : length (@var{y})}.  If @var{x}
48## is given it may be a string array, a cell array of strings, or a numerical
49## vector.
50##
51## If the first argument @var{hax} is an axes handle, then plot into this axes,
52## rather than the current axes returned by @code{gca}.
53##
54## The optional return value @var{h} is a 2-element vector with a graphics
55## handle for the created bar plot and a second handle for the created line
56## plot.
57##
58## An example of the use of @code{pareto} is
59##
60## @example
61## @group
62## Cheese = @{"Cheddar", "Swiss", "Camembert", ...
63##           "Munster", "Stilton", "Blue"@};
64## Sold = [105, 30, 70, 10, 15, 20];
65## pareto (Sold, Cheese);
66## @end group
67## @end example
68## @seealso{bar, barh, hist, pie, plot}
69## @end deftypefn
70
71function h = pareto (varargin)
72
73  [hax, varargin, nargin] = __plt_get_axis_arg__ ("pareto", varargin{:});
74
75  if (nargin != 1 && nargin != 2)
76    print_usage ();
77  endif
78
79  y = varargin{1}(:).';
80  if (nargin == 2)
81    x = varargin{2}(:).';
82    if (! iscell (x))
83      if (ischar (x))
84        x = cellstr (x);
85      else
86        x = cellstr (num2str (x(:)));
87      endif
88    endif
89  else
90    x = cellstr (int2str ([1:numel(y)]'));
91  endif
92
93  [y, idx] = sort (y, "descend");
94  x = x(idx);
95  cdf = cumsum (y);
96  maxcdf = cdf(end);
97  cdf ./= maxcdf;
98  idx95 = find (cdf < 0.95, 1, "last") + 1;
99
100  if (isempty (hax))
101    [ax, hbar, hline] = plotyy (1 : idx95, y(1:idx95),
102                                1 : length (cdf), 100 * cdf,
103                                @bar, @plot);
104  else
105    [ax, hbar, hline] = plotyy (hax, 1 : idx95, y(1:idx95),
106                                     1 : length (cdf), 100 * cdf,
107                                     @bar, @plot);
108  endif
109
110  axis (ax(1), [1 - 0.6, idx95 + 0.6, 0, maxcdf]);
111  axis (ax(2), [1 - 0.6, idx95 + 0.6, 0, 100]);
112  set (ax(2), "ytick", [0, 20, 40, 60, 80, 100],
113              "yticklabel", {"0%", "20%", "40%", "60%", "80%", "100%"},
114              "ycolor", get (ax(1), "ycolor"));
115  set (hline, "color", get (ax(1), "colororder")(1,:));
116  set (ax(1:2), "xtick", 1:idx95, "xticklabel", x(1:idx95));
117
118  if (nargout > 0)
119    h = [hbar; hline];
120  endif
121
122endfunction
123
124
125%!demo
126%! clf;
127%! colormap (jet (64));
128%! Cheese = {"Cheddar", "Swiss", "Camembert", "Munster", "Stilton", "Blue"};
129%! Sold = [105, 30, 70, 10, 15, 20];
130%! pareto (Sold, Cheese);
131%! title ("pareto() demo #1");
132
133%!demo
134%! clf;
135%! ## Suppose that we want establish which products makes 80% of turnover.
136%! Codes = {"AB4","BD7","CF8","CC5","AD11","BB5","BB3","AD8","DF3","DE7"};
137%! Value = [2.35 7.9 2.45 1.1 0.15 13.45 5.4 2.05 0.85 1.65]';
138%! SoldUnits = [54723 41114 16939 1576091 168000 687197 120222 168195, ...
139%!              1084118 55576]';
140%! pareto (Value.*SoldUnits, Codes);
141%! title ("pareto() demo #2");
142