@@ -8100,18 +8100,18 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
8100
8100
- ``cquantiles``: A `~.collections.LineCollection` instance created
8101
8101
to identify the quantiles values of each of the violin's
8102
8102
distribution.
8103
-
8104
8103
"""
8105
8104
8106
8105
# Statistical quantities to be plotted on the violins
8107
8106
means = []
8108
8107
mins = []
8109
8108
maxes = []
8110
8109
medians = []
8111
- quantiles = np .asarray ([])
8110
+ quantiles = []
8111
+
8112
+ qlens = [] # Number of quantiles in each dataset.
8112
8113
8113
- # Collections to be returned
8114
- artists = {}
8114
+ artists = {} # Collections to be returned
8115
8115
8116
8116
N = len (vpstats )
8117
8117
datashape_message = ("List of violinplot statistics and `{0}` "
@@ -8129,84 +8129,56 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
8129
8129
elif len (widths ) != N :
8130
8130
raise ValueError (datashape_message .format ("widths" ))
8131
8131
8132
- # Calculate ranges for statistics lines
8133
- pmins = - 0.25 * np .array (widths ) + positions
8134
- pmaxes = 0.25 * np .array (widths ) + positions
8132
+ # Calculate ranges for statistics lines (shape (2, N)).
8133
+ line_ends = [[- 0.25 ], [0.25 ]] * np .array (widths ) + positions
8134
+
8135
+ # Colors.
8136
+ if rcParams ['_internal.classic_mode' ]:
8137
+ fillcolor = 'y'
8138
+ linecolor = 'r'
8139
+ else :
8140
+ fillcolor = linecolor = self ._get_lines .get_next_color ()
8135
8141
8136
8142
# Check whether we are rendering vertically or horizontally
8137
8143
if vert :
8138
8144
fill = self .fill_betweenx
8139
- perp_lines = self .hlines
8140
- par_lines = self .vlines
8145
+ perp_lines = functools . partial ( self .hlines , colors = linecolor )
8146
+ par_lines = functools . partial ( self .vlines , colors = linecolor )
8141
8147
else :
8142
8148
fill = self .fill_between
8143
- perp_lines = self .vlines
8144
- par_lines = self .hlines
8145
-
8146
- if rcParams ['_internal.classic_mode' ]:
8147
- fillcolor = 'y'
8148
- edgecolor = 'r'
8149
- else :
8150
- fillcolor = edgecolor = self ._get_lines .get_next_color ()
8149
+ perp_lines = functools .partial (self .vlines , colors = linecolor )
8150
+ par_lines = functools .partial (self .hlines , colors = linecolor )
8151
8151
8152
8152
# Render violins
8153
8153
bodies = []
8154
8154
for stats , pos , width in zip (vpstats , positions , widths ):
8155
- # The 0.5 factor reflects the fact that we plot from v-p to
8156
- # v+p
8155
+ # The 0.5 factor reflects the fact that we plot from v-p to v+p.
8157
8156
vals = np .array (stats ['vals' ])
8158
8157
vals = 0.5 * width * vals / vals .max ()
8159
- bodies += [fill (stats ['coords' ],
8160
- - vals + pos ,
8161
- vals + pos ,
8162
- facecolor = fillcolor ,
8163
- alpha = 0.3 )]
8158
+ bodies += [fill (stats ['coords' ], - vals + pos , vals + pos ,
8159
+ facecolor = fillcolor , alpha = 0.3 )]
8164
8160
means .append (stats ['mean' ])
8165
8161
mins .append (stats ['min' ])
8166
8162
maxes .append (stats ['max' ])
8167
8163
medians .append (stats ['median' ])
8168
- q = stats .get ('quantiles' )
8169
- if q is not None :
8170
- # If exist key quantiles, assume it's a list of floats
8171
- quantiles = np .concatenate ((quantiles , q ))
8164
+ q = stats .get ('quantiles' ) # a list of floats, or None
8165
+ if q is None :
8166
+ q = []
8167
+ quantiles .extend (q )
8168
+ qlens .append (len (q ))
8172
8169
artists ['bodies' ] = bodies
8173
8170
8174
- # Render means
8175
- if showmeans :
8176
- artists ['cmeans' ] = perp_lines (means , pmins , pmaxes ,
8177
- colors = edgecolor )
8178
-
8179
- # Render extrema
8180
- if showextrema :
8181
- artists ['cmaxes' ] = perp_lines (maxes , pmins , pmaxes ,
8182
- colors = edgecolor )
8183
- artists ['cmins' ] = perp_lines (mins , pmins , pmaxes ,
8184
- colors = edgecolor )
8185
- artists ['cbars' ] = par_lines (positions , mins , maxes ,
8186
- colors = edgecolor )
8187
-
8188
- # Render medians
8189
- if showmedians :
8190
- artists ['cmedians' ] = perp_lines (medians ,
8191
- pmins ,
8192
- pmaxes ,
8193
- colors = edgecolor )
8194
-
8195
- # Render quantile values
8196
- if quantiles .size > 0 :
8197
- # Recalculate ranges for statistics lines for quantiles.
8198
- # ppmins are the left end of quantiles lines
8199
- ppmins = np .asarray ([])
8200
- # pmaxes are the right end of quantiles lines
8201
- ppmaxs = np .asarray ([])
8202
- for stats , cmin , cmax in zip (vpstats , pmins , pmaxes ):
8203
- q = stats .get ('quantiles' )
8204
- if q is not None :
8205
- ppmins = np .concatenate ((ppmins , [cmin ] * np .size (q )))
8206
- ppmaxs = np .concatenate ((ppmaxs , [cmax ] * np .size (q )))
8207
- # Start rendering
8208
- artists ['cquantiles' ] = perp_lines (quantiles , ppmins , ppmaxs ,
8209
- colors = edgecolor )
8171
+ if showmeans : # Render means
8172
+ artists ['cmeans' ] = perp_lines (means , * line_ends )
8173
+ if showextrema : # Render extrema
8174
+ artists ['cmaxes' ] = perp_lines (maxes , * line_ends )
8175
+ artists ['cmins' ] = perp_lines (mins , * line_ends )
8176
+ artists ['cbars' ] = par_lines (positions , mins , maxes )
8177
+ if showmedians : # Render medians
8178
+ artists ['cmedians' ] = perp_lines (medians , * line_ends )
8179
+ if quantiles : # Render quantiles: each width is repeated qlen times.
8180
+ idxs = [idx for idx , qlen in enumerate (qlens ) for _ in range (qlen )]
8181
+ artists ['cquantiles' ] = perp_lines (quantiles , * line_ends [:, idxs ])
8210
8182
8211
8183
return artists
8212
8184
0 commit comments