填充直方图

用于绘制直方图的剖面线功能。

  1. import itertools
  2. from collections import OrderedDict
  3. from functools import partial
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. import matplotlib.ticker as mticker
  7. from cycler import cycler
  8. def filled_hist(ax, edges, values, bottoms=None, orientation='v',
  9. **kwargs):
  10. """
  11. Draw a histogram as a stepped patch.
  12. Extra kwargs are passed through to `fill_between`
  13. Parameters
  14. ----------
  15. ax : Axes
  16. The axes to plot to
  17. edges : array
  18. A length n+1 array giving the left edges of each bin and the
  19. right edge of the last bin.
  20. values : array
  21. A length n array of bin counts or values
  22. bottoms : scalar or array, optional
  23. A length n array of the bottom of the bars. If None, zero is used.
  24. orientation : {'v', 'h'}
  25. Orientation of the histogram. 'v' (default) has
  26. the bars increasing in the positive y-direction.
  27. Returns
  28. -------
  29. ret : PolyCollection
  30. Artist added to the Axes
  31. """
  32. print(orientation)
  33. if orientation not in 'hv':
  34. raise ValueError("orientation must be in {{'h', 'v'}} "
  35. "not {o}".format(o=orientation))
  36. kwargs.setdefault('step', 'post')
  37. edges = np.asarray(edges)
  38. values = np.asarray(values)
  39. if len(edges) - 1 != len(values):
  40. raise ValueError('Must provide one more bin edge than value not: '
  41. 'len(edges): {lb} len(values): {lv}'.format(
  42. lb=len(edges), lv=len(values)))
  43. if bottoms is None:
  44. bottoms = np.zeros_like(values)
  45. if np.isscalar(bottoms):
  46. bottoms = np.ones_like(values) * bottoms
  47. values = np.r_[values, values[-1]]
  48. bottoms = np.r_[bottoms, bottoms[-1]]
  49. if orientation == 'h':
  50. return ax.fill_betweenx(edges, values, bottoms,
  51. **kwargs)
  52. elif orientation == 'v':
  53. return ax.fill_between(edges, values, bottoms,
  54. **kwargs)
  55. else:
  56. raise AssertionError("you should never be here")
  57. def stack_hist(ax, stacked_data, sty_cycle, bottoms=None,
  58. hist_func=None, labels=None,
  59. plot_func=None, plot_kwargs=None):
  60. """
  61. ax : axes.Axes
  62. The axes to add artists too
  63. stacked_data : array or Mapping
  64. A (N, M) shaped array. The first dimension will be iterated over to
  65. compute histograms row-wise
  66. sty_cycle : Cycler or operable of dict
  67. Style to apply to each set
  68. bottoms : array, optional
  69. The initial positions of the bottoms, defaults to 0
  70. hist_func : callable, optional
  71. Must have signature `bin_vals, bin_edges = f(data)`.
  72. `bin_edges` expected to be one longer than `bin_vals`
  73. labels : list of str, optional
  74. The label for each set.
  75. If not given and stacked data is an array defaults to 'default set {n}'
  76. If stacked_data is a mapping, and labels is None, default to the keys
  77. (which may come out in a random order).
  78. If stacked_data is a mapping and labels is given then only
  79. the columns listed by be plotted.
  80. plot_func : callable, optional
  81. Function to call to draw the histogram must have signature:
  82. ret = plot_func(ax, edges, top, bottoms=bottoms,
  83. label=label, **kwargs)
  84. plot_kwargs : dict, optional
  85. Any extra kwargs to pass through to the plotting function. This
  86. will be the same for all calls to the plotting function and will
  87. over-ride the values in cycle.
  88. Returns
  89. -------
  90. arts : dict
  91. Dictionary of artists keyed on their labels
  92. """
  93. # deal with default binning function
  94. if hist_func is None:
  95. hist_func = np.histogram
  96. # deal with default plotting function
  97. if plot_func is None:
  98. plot_func = filled_hist
  99. # deal with default
  100. if plot_kwargs is None:
  101. plot_kwargs = {}
  102. print(plot_kwargs)
  103. try:
  104. l_keys = stacked_data.keys()
  105. label_data = True
  106. if labels is None:
  107. labels = l_keys
  108. except AttributeError:
  109. label_data = False
  110. if labels is None:
  111. labels = itertools.repeat(None)
  112. if label_data:
  113. loop_iter = enumerate((stacked_data[lab], lab, s)
  114. for lab, s in zip(labels, sty_cycle))
  115. else:
  116. loop_iter = enumerate(zip(stacked_data, labels, sty_cycle))
  117. arts = {}
  118. for j, (data, label, sty) in loop_iter:
  119. if label is None:
  120. label = 'dflt set {n}'.format(n=j)
  121. label = sty.pop('label', label)
  122. vals, edges = hist_func(data)
  123. if bottoms is None:
  124. bottoms = np.zeros_like(vals)
  125. top = bottoms + vals
  126. print(sty)
  127. sty.update(plot_kwargs)
  128. print(sty)
  129. ret = plot_func(ax, edges, top, bottoms=bottoms,
  130. label=label, **sty)
  131. bottoms = top
  132. arts[label] = ret
  133. ax.legend(fontsize=10)
  134. return arts
  135. # set up histogram function to fixed bins
  136. edges = np.linspace(-3, 3, 20, endpoint=True)
  137. hist_func = partial(np.histogram, bins=edges)
  138. # set up style cycles
  139. color_cycle = cycler(facecolor=plt.rcParams['axes.prop_cycle'][:4])
  140. label_cycle = cycler(label=['set {n}'.format(n=n) for n in range(4)])
  141. hatch_cycle = cycler(hatch=['/', '*', '+', '|'])
  142. # Fixing random state for reproducibility
  143. np.random.seed(19680801)
  144. stack_data = np.random.randn(4, 12250)
  145. dict_data = OrderedDict(zip((c['label'] for c in label_cycle), stack_data))

使用普通数组

  1. fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4.5), tight_layout=True)
  2. arts = stack_hist(ax1, stack_data, color_cycle + label_cycle + hatch_cycle,
  3. hist_func=hist_func)
  4. arts = stack_hist(ax2, stack_data, color_cycle,
  5. hist_func=hist_func,
  6. plot_kwargs=dict(edgecolor='w', orientation='h'))
  7. ax1.set_ylabel('counts')
  8. ax1.set_xlabel('x')
  9. ax2.set_xlabel('counts')
  10. ax2.set_ylabel('x')

填充直方图

输出:

  1. {}
  2. {'facecolor': '#1f77b4', 'hatch': '/'}
  3. {'facecolor': '#1f77b4', 'hatch': '/'}
  4. v
  5. {'facecolor': '#ff7f0e', 'hatch': '*'}
  6. {'facecolor': '#ff7f0e', 'hatch': '*'}
  7. v
  8. {'facecolor': '#2ca02c', 'hatch': '+'}
  9. {'facecolor': '#2ca02c', 'hatch': '+'}
  10. v
  11. {'facecolor': '#d62728', 'hatch': '|'}
  12. {'facecolor': '#d62728', 'hatch': '|'}
  13. v
  14. {'edgecolor': 'w', 'orientation': 'h'}
  15. {'facecolor': '#1f77b4'}
  16. {'facecolor': '#1f77b4', 'edgecolor': 'w', 'orientation': 'h'}
  17. h
  18. {'facecolor': '#ff7f0e'}
  19. {'facecolor': '#ff7f0e', 'edgecolor': 'w', 'orientation': 'h'}
  20. h
  21. {'facecolor': '#2ca02c'}
  22. {'facecolor': '#2ca02c', 'edgecolor': 'w', 'orientation': 'h'}
  23. h
  24. {'facecolor': '#d62728'}
  25. {'facecolor': '#d62728', 'edgecolor': 'w', 'orientation': 'h'}
  26. h

使用标记数据

  1. fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4.5),
  2. tight_layout=True, sharey=True)
  3. arts = stack_hist(ax1, dict_data, color_cycle + hatch_cycle,
  4. hist_func=hist_func)
  5. arts = stack_hist(ax2, dict_data, color_cycle + hatch_cycle,
  6. hist_func=hist_func, labels=['set 0', 'set 3'])
  7. ax1.xaxis.set_major_locator(mticker.MaxNLocator(5))
  8. ax1.set_xlabel('counts')
  9. ax1.set_ylabel('x')
  10. ax2.set_ylabel('x')
  11. plt.show()

填充直方图2

输出:

  1. {}
  2. {'facecolor': '#1f77b4', 'hatch': '/'}
  3. {'facecolor': '#1f77b4', 'hatch': '/'}
  4. v
  5. {'facecolor': '#ff7f0e', 'hatch': '*'}
  6. {'facecolor': '#ff7f0e', 'hatch': '*'}
  7. v
  8. {'facecolor': '#2ca02c', 'hatch': '+'}
  9. {'facecolor': '#2ca02c', 'hatch': '+'}
  10. v
  11. {'facecolor': '#d62728', 'hatch': '|'}
  12. {'facecolor': '#d62728', 'hatch': '|'}
  13. v
  14. {}
  15. {'facecolor': '#1f77b4', 'hatch': '/'}
  16. {'facecolor': '#1f77b4', 'hatch': '/'}
  17. v
  18. {'facecolor': '#ff7f0e', 'hatch': '*'}
  19. {'facecolor': '#ff7f0e', 'hatch': '*'}
  20. v

参考

此示例中显示了以下函数,方法,类和模块的使用:

  1. import matplotlib
  2. matplotlib.axes.Axes.fill_betweenx
  3. matplotlib.axes.Axes.fill_between
  4. matplotlib.axis.Axis.set_major_locator

下载这个示例