@@ -137,7 +137,7 @@ def make_mapping(args, variable):
137137 )
138138
139139
140- def make_trace_kwargs (args , trace_spec , g , mapping_labels , sizeref ):
140+ def make_trace_kwargs (args , trace_spec , trace_data , mapping_labels , sizeref ):
141141 """Populates a dict with arguments to update trace
142142
143143 Parameters
@@ -147,7 +147,7 @@ def make_trace_kwargs(args, trace_spec, g, mapping_labels, sizeref):
147147 trace_spec : NamedTuple
148148 which kind of trace to be used (has constructor, marginal etc.
149149 attributes)
150- g : pandas DataFrame
150+ trace_data : pandas DataFrame
151151 data
152152 mapping_labels : dict
153153 to be used for hovertemplate
@@ -156,87 +156,92 @@ def make_trace_kwargs(args, trace_spec, g, mapping_labels, sizeref):
156156
157157 Returns
158158 -------
159- result : dict
159+ trace_patch : dict
160160 dict to be used to update trace
161161 fit_results : dict
162162 fit information to be used for trendlines
163163 """
164164 if "line_close" in args and args ["line_close" ]:
165- g = g .append (g .iloc [0 ])
166- result = trace_spec .trace_patch .copy () or {}
165+ trace_data = trace_data .append (trace_data .iloc [0 ])
166+ trace_patch = trace_spec .trace_patch .copy () or {}
167167 fit_results = None
168168 hover_header = ""
169169 custom_data_len = 0
170- for k in trace_spec .attrs :
171- v = args [k ]
172- v_label = get_decorated_label (args , v , k )
173- if k == "dimensions" :
170+ for attr_name in trace_spec .attrs :
171+ attr_value = args [attr_name ]
172+ attr_label = get_decorated_label (args , attr_value , attr_name )
173+ if attr_name == "dimensions" :
174174 dims = [
175175 (name , column )
176- for (name , column ) in g .iteritems ()
177- if ((not v ) or (name in v ))
176+ for (name , column ) in trace_data .iteritems ()
177+ if ((not attr_value ) or (name in attr_value ))
178178 and (
179179 trace_spec .constructor != go .Parcoords
180180 or args ["data_frame" ][name ].dtype .kind in "bifc"
181181 )
182182 and (
183183 trace_spec .constructor != go .Parcats
184- or (v is not None and name in v )
184+ or (attr_value is not None and name in attr_value )
185185 or len (args ["data_frame" ][name ].unique ())
186186 <= args ["dimensions_max_cardinality" ]
187187 )
188188 ]
189- result ["dimensions" ] = [
189+ trace_patch ["dimensions" ] = [
190190 dict (label = get_label (args , name ), values = column .values )
191191 for (name , column ) in dims
192192 ]
193193 if trace_spec .constructor == go .Splom :
194- for d in result ["dimensions" ]:
194+ for d in trace_patch ["dimensions" ]:
195195 d ["axis" ] = dict (matches = True )
196196 mapping_labels ["%{xaxis.title.text}" ] = "%{x}"
197197 mapping_labels ["%{yaxis.title.text}" ] = "%{y}"
198198
199199 elif (
200- v is not None
201- or (trace_spec .constructor == go .Histogram and k in ["x" , "y" ])
200+ attr_value is not None
201+ or (trace_spec .constructor == go .Histogram and attr_name in ["x" , "y" ])
202202 or (
203203 trace_spec .constructor in [go .Histogram2d , go .Histogram2dContour ]
204- and k == "z"
204+ and attr_name == "z"
205205 )
206206 ):
207- if k == "size" :
208- if "marker" not in result :
209- result ["marker" ] = dict ()
210- result ["marker" ]["size" ] = g [ v ]
211- result ["marker" ]["sizemode" ] = "area"
212- result ["marker" ]["sizeref" ] = sizeref
213- mapping_labels [v_label ] = "%{marker.size}"
214- elif k == "marginal_x" :
207+ if attr_name == "size" :
208+ if "marker" not in trace_patch :
209+ trace_patch ["marker" ] = dict ()
210+ trace_patch ["marker" ]["size" ] = trace_data [ attr_value ]
211+ trace_patch ["marker" ]["sizemode" ] = "area"
212+ trace_patch ["marker" ]["sizeref" ] = sizeref
213+ mapping_labels [attr_label ] = "%{marker.size}"
214+ elif attr_name == "marginal_x" :
215215 if trace_spec .constructor == go .Histogram :
216216 mapping_labels ["count" ] = "%{y}"
217- elif k == "marginal_y" :
217+ elif attr_name == "marginal_y" :
218218 if trace_spec .constructor == go .Histogram :
219219 mapping_labels ["count" ] = "%{x}"
220- elif k == "trendline" :
221- if v in ["ols" , "lowess" ] and args ["x" ] and args ["y" ] and len (g ) > 1 :
220+ elif attr_name == "trendline" :
221+ if (
222+ attr_value in ["ols" , "lowess" ]
223+ and args ["x" ]
224+ and args ["y" ]
225+ and len (trace_data ) > 1
226+ ):
222227 import statsmodels .api as sm
223228
224229 # sorting is bad but trace_specs with "trendline" have no other attrs
225- g2 = g .sort_values (by = args ["x" ])
226- y = g2 [args ["y" ]]
227- x = g2 [args ["x" ]]
228- result ["x" ] = x
230+ sorted_trace_data = trace_data .sort_values (by = args ["x" ])
231+ y = sorted_trace_data [args ["y" ]]
232+ x = sorted_trace_data [args ["x" ]]
233+ trace_patch ["x" ] = x
229234
230235 if x .dtype .type == np .datetime64 :
231236 x = x .astype (int ) / 10 ** 9 # convert to unix epoch seconds
232237
233- if v == "lowess" :
238+ if attr_value == "lowess" :
234239 trendline = sm .nonparametric .lowess (y , x )
235- result ["y" ] = trendline [:, 1 ]
240+ trace_patch ["y" ] = trendline [:, 1 ]
236241 hover_header = "<b>LOWESS trendline</b><br><br>"
237- elif v == "ols" :
242+ elif attr_value == "ols" :
238243 fit_results = sm .OLS (y .values , sm .add_constant (x .values )).fit ()
239- result ["y" ] = fit_results .predict ()
244+ trace_patch ["y" ] = fit_results .predict ()
240245 hover_header = "<b>OLS trendline</b><br>"
241246 hover_header += "%s = %g * %s + %g<br>" % (
242247 args ["y" ],
@@ -250,120 +255,127 @@ def make_trace_kwargs(args, trace_spec, g, mapping_labels, sizeref):
250255 mapping_labels [get_label (args , args ["x" ])] = "%{x}"
251256 mapping_labels [get_label (args , args ["y" ])] = "%{y} <b>(trend)</b>"
252257
253- elif k .startswith ("error" ):
254- error_xy = k [:7 ]
255- arr = "arrayminus" if k .endswith ("minus" ) else "array"
256- if error_xy not in result :
257- result [error_xy ] = {}
258- result [error_xy ][arr ] = g [ v ]
259- elif k == "custom_data" :
260- result ["customdata" ] = g [ v ].values
261- custom_data_len = len (v ) # number of custom data columns
262- elif k == "hover_name" :
258+ elif attr_name .startswith ("error" ):
259+ error_xy = attr_name [:7 ]
260+ arr = "arrayminus" if attr_name .endswith ("minus" ) else "array"
261+ if error_xy not in trace_patch :
262+ trace_patch [error_xy ] = {}
263+ trace_patch [error_xy ][arr ] = trace_data [ attr_value ]
264+ elif attr_name == "custom_data" :
265+ trace_patch ["customdata" ] = trace_data [ attr_value ].values
266+ custom_data_len = len (attr_value ) # number of custom data columns
267+ elif attr_name == "hover_name" :
263268 if trace_spec .constructor not in [
264269 go .Histogram ,
265270 go .Histogram2d ,
266271 go .Histogram2dContour ,
267272 ]:
268- result ["hovertext" ] = g [ v ]
273+ trace_patch ["hovertext" ] = trace_data [ attr_value ]
269274 if hover_header == "" :
270275 hover_header = "<b>%{hovertext}</b><br><br>"
271- elif k == "hover_data" :
276+ elif attr_name == "hover_data" :
272277 if trace_spec .constructor not in [
273278 go .Histogram ,
274279 go .Histogram2d ,
275280 go .Histogram2dContour ,
276281 ]:
277- for col in v :
282+ for col in attr_value :
278283 try :
279284 position = args ["custom_data" ].index (col )
280285 except (ValueError , AttributeError , KeyError ):
281286 position = custom_data_len
282287 custom_data_len += 1
283- if "customdata" in result :
284- result ["customdata" ] = np .hstack (
285- (result ["customdata" ], g [col ].values [:, None ])
288+ if "customdata" in trace_patch :
289+ trace_patch ["customdata" ] = np .hstack (
290+ (
291+ trace_patch ["customdata" ],
292+ trace_data [col ].values [:, None ],
293+ )
286294 )
287295 else :
288- result ["customdata" ] = g [col ].values [:, None ]
289- v_label_col = get_decorated_label (args , col , None )
290- mapping_labels [v_label_col ] = "%%{customdata[%d]}" % (position )
291- elif k == "color" :
296+ trace_patch ["customdata" ] = trace_data [col ].values [
297+ :, None
298+ ]
299+ attr_label_col = get_decorated_label (args , col , None )
300+ mapping_labels [attr_label_col ] = "%%{customdata[%d]}" % (
301+ position
302+ )
303+ elif attr_name == "color" :
292304 if trace_spec .constructor in [go .Choropleth , go .Choroplethmapbox ]:
293- result ["z" ] = g [ v ]
294- result ["coloraxis" ] = "coloraxis1"
295- mapping_labels [v_label ] = "%{z}"
305+ trace_patch ["z" ] = trace_data [ attr_value ]
306+ trace_patch ["coloraxis" ] = "coloraxis1"
307+ mapping_labels [attr_label ] = "%{z}"
296308 elif trace_spec .constructor in [
297309 go .Sunburst ,
298310 go .Treemap ,
299311 go .Pie ,
300312 go .Funnelarea ,
301313 ]:
302- if "marker" not in result :
303- result ["marker" ] = dict ()
314+ if "marker" not in trace_patch :
315+ trace_patch ["marker" ] = dict ()
304316
305317 if args .get ("color_is_continuous" ):
306- result ["marker" ]["colors" ] = g [ v ]
307- result ["marker" ]["coloraxis" ] = "coloraxis1"
308- mapping_labels [v_label ] = "%{color}"
318+ trace_patch ["marker" ]["colors" ] = trace_data [ attr_value ]
319+ trace_patch ["marker" ]["coloraxis" ] = "coloraxis1"
320+ mapping_labels [attr_label ] = "%{color}"
309321 else :
310- result ["marker" ]["colors" ] = []
322+ trace_patch ["marker" ]["colors" ] = []
311323 mapping = {}
312- for cat in g [ v ]:
324+ for cat in trace_data [ attr_value ]:
313325 if mapping .get (cat ) is None :
314326 mapping [cat ] = args ["color_discrete_sequence" ][
315327 len (mapping ) % len (args ["color_discrete_sequence" ])
316328 ]
317- result ["marker" ]["colors" ].append (mapping [cat ])
329+ trace_patch ["marker" ]["colors" ].append (mapping [cat ])
318330 else :
319331 colorable = "marker"
320332 if trace_spec .constructor in [go .Parcats , go .Parcoords ]:
321333 colorable = "line"
322- if colorable not in result :
323- result [colorable ] = dict ()
324- result [colorable ]["color" ] = g [ v ]
325- result [colorable ]["coloraxis" ] = "coloraxis1"
326- mapping_labels [v_label ] = "%%{%s.color}" % colorable
327- elif k == "animation_group" :
328- result ["ids" ] = g [ v ]
329- elif k == "locations" :
330- result [ k ] = g [ v ]
331- mapping_labels [v_label ] = "%{location}"
332- elif k == "values" :
333- result [ k ] = g [ v ]
334- _label = "value" if v_label == "values" else v_label
334+ if colorable not in trace_patch :
335+ trace_patch [colorable ] = dict ()
336+ trace_patch [colorable ]["color" ] = trace_data [ attr_value ]
337+ trace_patch [colorable ]["coloraxis" ] = "coloraxis1"
338+ mapping_labels [attr_label ] = "%%{%s.color}" % colorable
339+ elif attr_name == "animation_group" :
340+ trace_patch ["ids" ] = trace_data [ attr_value ]
341+ elif attr_name == "locations" :
342+ trace_patch [ attr_name ] = trace_data [ attr_value ]
343+ mapping_labels [attr_label ] = "%{location}"
344+ elif attr_name == "values" :
345+ trace_patch [ attr_name ] = trace_data [ attr_value ]
346+ _label = "value" if attr_label == "values" else attr_label
335347 mapping_labels [_label ] = "%{value}"
336- elif k == "parents" :
337- result [ k ] = g [ v ]
338- _label = "parent" if v_label == "parents" else v_label
348+ elif attr_name == "parents" :
349+ trace_patch [ attr_name ] = trace_data [ attr_value ]
350+ _label = "parent" if attr_label == "parents" else attr_label
339351 mapping_labels [_label ] = "%{parent}"
340- elif k == "ids" :
341- result [ k ] = g [ v ]
342- _label = "id" if v_label == "ids" else v_label
352+ elif attr_name == "ids" :
353+ trace_patch [ attr_name ] = trace_data [ attr_value ]
354+ _label = "id" if attr_label == "ids" else attr_label
343355 mapping_labels [_label ] = "%{id}"
344- elif k == "names" :
356+ elif attr_name == "names" :
345357 if trace_spec .constructor in [
346358 go .Sunburst ,
347359 go .Treemap ,
348360 go .Pie ,
349361 go .Funnelarea ,
350362 ]:
351- result ["labels" ] = g [ v ]
352- _label = "label" if v_label == "names" else v_label
363+ trace_patch ["labels" ] = trace_data [ attr_value ]
364+ _label = "label" if attr_label == "names" else attr_label
353365 mapping_labels [_label ] = "%{label}"
354366 else :
355- result [ k ] = g [ v ]
367+ trace_patch [ attr_name ] = trace_data [ attr_value ]
356368 else :
357- if v :
358- result [ k ] = g [ v ]
359- mapping_labels [v_label ] = "%%{%s}" % k
369+ if attr_value :
370+ trace_patch [ attr_name ] = trace_data [ attr_value ]
371+ mapping_labels [attr_label ] = "%%{%s}" % attr_name
360372 if trace_spec .constructor not in [
361373 go .Parcoords ,
362374 go .Parcats ,
363375 ]:
364376 hover_lines = [k + "=" + v for k , v in mapping_labels .items ()]
365- result ["hovertemplate" ] = hover_header + "<br>" .join (hover_lines )
366- return result , fit_results
377+ trace_patch ["hovertemplate" ] = hover_header + "<br>" .join (hover_lines )
378+ return trace_patch , fit_results
367379
368380
369381def configure_axes (args , constructor , fig , orders ):
@@ -1015,8 +1027,8 @@ def _check_dataframe_all_leaves(df):
10151027 null_indices = np .nonzero (null_mask .any (axis = 1 ).values )[0 ]
10161028 for null_row_index in null_indices :
10171029 row = null_mask .iloc [null_row_index ]
1018- indices = np .nonzero (row .values )[0 ]
1019- if not row [indices [ 0 ] :].all ():
1030+ i = np .nonzero (row .values )[ 0 ] [0 ]
1031+ if not row [i :].all ():
10201032 raise ValueError (
10211033 "None entries cannot have not-None children" ,
10221034 df_sorted .iloc [null_row_index ],
@@ -1058,6 +1070,7 @@ def process_dataframe_hierarchy(args):
10581070 path = [new_col_name if x == col_name else x for x in path ]
10591071 df [new_col_name ] = series_to_copy
10601072 # ------------ Define aggregation functions --------------------------------
1073+
10611074 def aggfunc_discrete (x ):
10621075 uniques = x .unique ()
10631076 if len (uniques ) == 1 :
0 commit comments