@@ -142,6 +142,10 @@ def _has_3d_geoms(self, plot):
142142 return True
143143 return False
144144
145+ def _is_no_facet (self , value ):
146+ """Check if value means 'no faceting on this dimension'."""
147+ return value is None or value == '.'
148+
145149 def apply (self , plot ):
146150 """
147151 Apply facet grid to the plot.
@@ -155,25 +159,29 @@ def apply(self, plot):
155159 Raises:
156160 FacetColumnNotFoundError: If row or column variable doesn't exist in the data.
157161 """
158- # Validate row facet column exists
159- if self .rows not in plot .data .columns :
162+ # Check if rows/cols are disabled (None or '.')
163+ has_rows = not self ._is_no_facet (self .rows )
164+ has_cols = not self ._is_no_facet (self .cols )
165+
166+ # Validate row facet column exists (if specified)
167+ if has_rows and self .rows not in plot .data .columns :
160168 raise FacetColumnNotFoundError (
161169 self .rows ,
162170 list (plot .data .columns ),
163171 facet_type = "facet_grid rows"
164172 )
165173
166- # Validate column facet column exists
167- if self .cols not in plot .data .columns :
174+ # Validate column facet column exists (if specified)
175+ if has_cols and self .cols not in plot .data .columns :
168176 raise FacetColumnNotFoundError (
169177 self .cols ,
170178 list (plot .data .columns ),
171179 facet_type = "facet_grid cols"
172180 )
173181
174182 # Get unique values for the row and column variables
175- row_facets = plot .data [self .rows ].unique ()
176- col_facets = plot .data [self .cols ].unique ()
183+ row_facets = plot .data [self .rows ].unique () if has_rows else [ None ]
184+ col_facets = plot .data [self .cols ].unique () if has_cols else [ None ]
177185
178186 nrows = len (row_facets )
179187 ncols = len (col_facets )
@@ -192,14 +200,22 @@ def apply(self, plot):
192200 shared_y = self .scales in ('fixed' , 'free_x' )
193201
194202 # Generate labels
195- labels = [self ._get_label (self .rows , row , self .cols , col )
196- for row in row_facets for col in col_facets ]
203+ def get_facet_label (row , col ):
204+ if has_rows and has_cols :
205+ return self ._get_label (self .rows , row , self .cols , col )
206+ elif has_rows :
207+ return str (row )
208+ elif has_cols :
209+ return str (col )
210+ else :
211+ return ""
212+ labels = [get_facet_label (row , col ) for row in row_facets for col in col_facets ]
197213
198214 # Calculate column widths and row heights based on space parameter
199215 column_widths = None
200216 row_heights = None
201217
202- if self .space in ('free' , 'free_x' ):
218+ if self .space in ('free' , 'free_x' ) and has_cols :
203219 # Calculate width proportional to x-axis data range per column
204220 x_col = plot .mapping .get ('x' )
205221 if x_col and x_col in plot .data .columns :
@@ -214,7 +230,7 @@ def apply(self, plot):
214230 if total > 0 :
215231 column_widths = [r / total for r in col_ranges ]
216232
217- if self .space in ('free' , 'free_y' ):
233+ if self .space in ('free' , 'free_y' ) and has_rows :
218234 # Calculate height proportional to y-axis data range per row
219235 y_col = plot .mapping .get ('y' )
220236 if y_col and y_col in plot .data .columns :
@@ -269,10 +285,17 @@ def apply(self, plot):
269285 scene_key = None
270286
271287 # Subset data for the current facet (row and column combination)
272- facet_data = plot .data [
273- (plot .data [self .rows ] == row_value )
274- & (plot .data [self .cols ] == col_value )
275- ]
288+ if has_rows and has_cols :
289+ facet_data = plot .data [
290+ (plot .data [self .rows ] == row_value )
291+ & (plot .data [self .cols ] == col_value )
292+ ]
293+ elif has_rows :
294+ facet_data = plot .data [plot .data [self .rows ] == row_value ]
295+ elif has_cols :
296+ facet_data = plot .data [plot .data [self .cols ] == col_value ]
297+ else :
298+ facet_data = plot .data
276299
277300 # Draw each geom on the subplot for the current facet
278301 for geom in plot .layers :
@@ -281,10 +304,17 @@ def apply(self, plot):
281304
282305 # If geom has its own explicit data, use that for faceting instead of plot.data
283306 if hasattr (geom , '_has_explicit_data' ) and geom ._has_explicit_data :
284- geom_facet_data = geom .data [
285- (geom .data [self .rows ] == row_value )
286- & (geom .data [self .cols ] == col_value )
287- ]
307+ if has_rows and has_cols :
308+ geom_facet_data = geom .data [
309+ (geom .data [self .rows ] == row_value )
310+ & (geom .data [self .cols ] == col_value )
311+ ]
312+ elif has_rows :
313+ geom_facet_data = geom .data [geom .data [self .rows ] == row_value ]
314+ elif has_cols :
315+ geom_facet_data = geom .data [geom .data [self .cols ] == col_value ]
316+ else :
317+ geom_facet_data = geom .data
288318 geom .setup_data (geom_facet_data , plot .mapping )
289319 else :
290320 geom .setup_data (facet_data , plot .mapping )
0 commit comments