Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/matplotlib/stackplot.py: 11%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

45 statements  

1""" 

2Stacked area plot for 1D arrays inspired by Douglas Y'barbo's stackoverflow 

3answer: 

4https://stackoverflow.com/q/2225995/ 

5 

6(https://stackoverflow.com/users/66549/doug) 

7""" 

8 

9import itertools 

10 

11import numpy as np 

12 

13from matplotlib import _api 

14 

15__all__ = ['stackplot'] 

16 

17 

18def stackplot(axes, x, *args, 

19 labels=(), colors=None, hatch=None, baseline='zero', 

20 **kwargs): 

21 """ 

22 Draw a stacked area plot or a streamgraph. 

23 

24 Parameters 

25 ---------- 

26 x : (N,) array-like 

27 

28 y : (M, N) array-like 

29 The data is assumed to be unstacked. Each of the following 

30 calls is legal:: 

31 

32 stackplot(x, y) # where y has shape (M, N) 

33 stackplot(x, y1, y2, y3) # where y1, y2, y3, y4 have length N 

34 

35 baseline : {'zero', 'sym', 'wiggle', 'weighted_wiggle'} 

36 Method used to calculate the baseline: 

37 

38 - ``'zero'``: Constant zero baseline, i.e. a simple stacked plot. 

39 - ``'sym'``: Symmetric around zero and is sometimes called 

40 'ThemeRiver'. 

41 - ``'wiggle'``: Minimizes the sum of the squared slopes. 

42 - ``'weighted_wiggle'``: Does the same but weights to account for 

43 size of each layer. It is also called 'Streamgraph'-layout. More 

44 details can be found at http://leebyron.com/streamgraph/. 

45 

46 labels : list of str, optional 

47 A sequence of labels to assign to each data series. If unspecified, 

48 then no labels will be applied to artists. 

49 

50 colors : list of :mpltype:`color`, optional 

51 A sequence of colors to be cycled through and used to color the stacked 

52 areas. The sequence need not be exactly the same length as the number 

53 of provided *y*, in which case the colors will repeat from the 

54 beginning. 

55 

56 If not specified, the colors from the Axes property cycle will be used. 

57 

58 hatch : list of str, default: None 

59 A sequence of hatching styles. See 

60 :doc:`/gallery/shapes_and_collections/hatch_style_reference`. 

61 The sequence will be cycled through for filling the 

62 stacked areas from bottom to top. 

63 It need not be exactly the same length as the number 

64 of provided *y*, in which case the styles will repeat from the 

65 beginning. 

66 

67 .. versionadded:: 3.9 

68 Support for list input 

69 

70 data : indexable object, optional 

71 DATA_PARAMETER_PLACEHOLDER 

72 

73 **kwargs 

74 All other keyword arguments are passed to `.Axes.fill_between`. 

75 

76 Returns 

77 ------- 

78 list of `.PolyCollection` 

79 A list of `.PolyCollection` instances, one for each element in the 

80 stacked area plot. 

81 """ 

82 

83 y = np.vstack(args) 

84 

85 labels = iter(labels) 

86 if colors is not None: 

87 colors = itertools.cycle(colors) 

88 else: 

89 colors = (axes._get_lines.get_next_color() for _ in y) 

90 

91 if hatch is None or isinstance(hatch, str): 

92 hatch = itertools.cycle([hatch]) 

93 else: 

94 hatch = itertools.cycle(hatch) 

95 

96 # Assume data passed has not been 'stacked', so stack it here. 

97 # We'll need a float buffer for the upcoming calculations. 

98 stack = np.cumsum(y, axis=0, dtype=np.promote_types(y.dtype, np.float32)) 

99 

100 _api.check_in_list(['zero', 'sym', 'wiggle', 'weighted_wiggle'], 

101 baseline=baseline) 

102 if baseline == 'zero': 

103 first_line = 0. 

104 

105 elif baseline == 'sym': 

106 first_line = -np.sum(y, 0) * 0.5 

107 stack += first_line[None, :] 

108 

109 elif baseline == 'wiggle': 

110 m = y.shape[0] 

111 first_line = (y * (m - 0.5 - np.arange(m)[:, None])).sum(0) 

112 first_line /= -m 

113 stack += first_line 

114 

115 elif baseline == 'weighted_wiggle': 

116 total = np.sum(y, 0) 

117 # multiply by 1/total (or zero) to avoid infinities in the division: 

118 inv_total = np.zeros_like(total) 

119 mask = total > 0 

120 inv_total[mask] = 1.0 / total[mask] 

121 increase = np.hstack((y[:, 0:1], np.diff(y))) 

122 below_size = total - stack 

123 below_size += 0.5 * y 

124 move_up = below_size * inv_total 

125 move_up[:, 0] = 0.5 

126 center = (move_up - 0.5) * increase 

127 center = np.cumsum(center.sum(0)) 

128 first_line = center - 0.5 * total 

129 stack += first_line 

130 

131 # Color between x = 0 and the first array. 

132 coll = axes.fill_between(x, first_line, stack[0, :], 

133 facecolor=next(colors), 

134 hatch=next(hatch), 

135 label=next(labels, None), 

136 **kwargs) 

137 coll.sticky_edges.y[:] = [0] 

138 r = [coll] 

139 

140 # Color between array i-1 and array i 

141 for i in range(len(y) - 1): 

142 r.append(axes.fill_between(x, stack[i, :], stack[i + 1, :], 

143 facecolor=next(colors), 

144 hatch=next(hatch), 

145 label=next(labels, None), 

146 **kwargs)) 

147 return r