@@ -10305,8 +10305,62 @@ def draw_batch(self,
1030510305 print (f"Materializing { len (to_materialize )} aliases: { sorted (to_materialize )} " )
1030610306 self .materialize_aliases (names = list (to_materialize ))
1030710307
10308+ # =================================================================
10309+ # Subframe column resolution for draw_batch
10310+ # Same logic as draw() — detect Subframe.column patterns across
10311+ # all specs, materialize as temporary columns, rewrite expressions.
10312+ # =================================================================
10313+ subframe_replacements = {}
10314+ df_for_plot = self .df
10315+ if hasattr (self , '_subframes' ) and hasattr (self ._subframes , 'subframes' ):
10316+ sf_names = set (self ._subframes .subframes .keys ())
10317+ merged_defaults = {** (defaults or {}), ** kwargs }
10318+
10319+ # Collect all text across all specs
10320+ all_text_parts = []
10321+ for name , spec in specs .items ():
10322+ merged_spec = {** merged_defaults , ** spec }
10323+ all_text_parts .append (merged_spec .get ('expr' , name ))
10324+ if merged_spec .get ('selection' ):
10325+ all_text_parts .append (merged_spec ['selection' ])
10326+ if merged_spec .get ('group_by' ):
10327+ all_text_parts .append (str (merged_spec ['group_by' ]))
10328+ all_text = ' ' .join (all_text_parts )
10329+
10330+ import re as _re
10331+ for match in _re .finditer (r'\b(\w+)\.(\w+)\b' , all_text ):
10332+ sf_name , col_name = match .group (1 ), match .group (2 )
10333+ if sf_name in sf_names :
10334+ dot_ref = f"{ sf_name } .{ col_name } "
10335+ flat_ref = f"{ sf_name } _{ col_name } "
10336+ if flat_ref not in df_for_plot .columns and dot_ref not in subframe_replacements :
10337+ try :
10338+ sf = self .get_subframe (sf_name )
10339+ index_cols = self ._subframes .get_entry (sf_name )['index' ]
10340+ if isinstance (index_cols , str ):
10341+ index_cols = [index_cols ]
10342+ join_idx , missing = self ._compute_join_indices (sf_name , index_cols )
10343+ if col_name in sf .df .columns :
10344+ if df_for_plot is self .df :
10345+ df_for_plot = df_for_plot .copy ()
10346+ df_for_plot [flat_ref ] = sf .df [col_name ].values [join_idx ]
10347+ subframe_replacements [dot_ref ] = flat_ref
10348+ except Exception :
10349+ pass
10350+
10351+ # Rewrite all specs: replace Sub.col → Sub_col
10352+ if subframe_replacements :
10353+ for name , spec in specs .items ():
10354+ for dot_ref , flat_ref in subframe_replacements .items ():
10355+ if 'expr' in spec :
10356+ spec ['expr' ] = spec ['expr' ].replace (dot_ref , flat_ref )
10357+ if 'selection' in spec and spec ['selection' ]:
10358+ spec ['selection' ] = spec ['selection' ].replace (dot_ref , flat_ref )
10359+ if 'group_by' in spec and isinstance (spec .get ('group_by' ), str ):
10360+ spec ['group_by' ] = spec ['group_by' ].replace (dot_ref , flat_ref )
10361+
1030810362 # Delegate to dfdraw batch
10309- plotter = DFDraw (self . df )
10363+ plotter = DFDraw (df_for_plot )
1031010364 plotter ._data_source = self # For duck-typed axis title lookup
1031110365
1031210366 results = plotter .draw_batch (
0 commit comments