Skip to content

Facets don't work with non-mapped geoms #48

@naught101

Description

@naught101

In ggplot2, it's possible to do this:

df = data.frame(a = rep(c(1,2), 100), b=rnorm(200), c=rnorm(200))
ggplot(df, aes(x=b, y=c)) + geom_point() + geom_abline(intercept=0, slope=1) + facet_wrap('a')

ggplot2_wrap_abline

in plotnine, the equivalent doesn't work:

df = pd.DataFrame(dict(a=['a','b'] * 100, b=np.random.random(200), c=np.random.random(200)))
ggplot(df, aes(x='b', y='c')) + geom_point() + \
    geom_abline(intercept=0, slope=1) + \
    facet_wrap('a')


Out[38]: ---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
~/miniconda3/envs/science/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj)
    691                 type_pprinters=self.type_printers,
    692                 deferred_pprinters=self.deferred_printers)
--> 693             printer.pretty(obj)
    694             printer.flush()
    695             return stream.getvalue()

~/miniconda3/envs/science/lib/python3.6/site-packages/IPython/lib/pretty.py in pretty(self, obj)
    378                             if callable(meth):
    379                                 return meth(obj, self, cycle)
--> 380             return _default_pprint(obj, self, cycle)
    381         finally:
    382             self.end_group()

~/miniconda3/envs/science/lib/python3.6/site-packages/IPython/lib/pretty.py in _default_pprint(obj, p, cycle)                                                                                                 
    493     if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
    494         # A user-provided repr. Find newlines and replace them with p.break_()
--> 495         _repr_pprint(obj, p, cycle)
    496         return
    497     p.begin_group(1, '<')

~/miniconda3/envs/science/lib/python3.6/site-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)                                                                                                    
    691     """A pprint that just redirects to the normal repr function."""
    692     # Find newlines and replace them with p.break_()
--> 693     output = repr(obj)
    694     for idx,output_line in enumerate(output.splitlines()):
    695         if idx:

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/ggplot.py in __repr__(self)
     82         Print/show the plot
     83         """
---> 84         self.draw()
     85         plt.show()
     86         return '<ggplot: (%d)>' % self.__hash__()

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/ggplot.py in draw(self)
    139         # assign a default theme
    140         self = deepcopy(self)
--> 141         self._build()
    142 
    143         # If no theme we use the default

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/ggplot.py in _build(self)
    220         # Initialise panels, add extra data for margins & missing
    221         # facetting variables, and add on a PANEL variable to data
--> 222         layout.setup(layers, self)
    223 
    224         # Compute aesthetics to produce data with generalised

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/facets/layout.py in setup(self, layers, plot)                                                                                                  
     57         # Generate panel layout
     58         data = self.facet.setup_data(data)
---> 59         self.layout = self.facet.compute_layout(data)
     60         self.layout = self.coord.setup_layout(self.layout)
     61         self.check_layout()

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/facets/facet_wrap.py in compute_layout(self, data)                                                                                             
     71 
     72         base = combine_vars(data, self.plot.environment,
---> 73                             self.vars, drop=self.drop)
     74         n = len(base)
     75         dims = wrap_dims(n, self.nrow, self.ncol)

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/facets/facet.py in combine_vars(data, environment, vars, drop)                                                                                 
    520     # For each layer, compute the facet values
    521     values = [eval_facet_vars(df, vars, environment)
--> 522               for df in data if df is not None]
    523 
    524     # Form the base data frame which contains all combinations

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/facets/facet.py in <listcomp>(.0)
    520     # For each layer, compute the facet values
    521     values = [eval_facet_vars(df, vars, environment)
--> 522               for df in data if df is not None]
    523 
    524     # Form the base data frame which contains all combinations

~/miniconda3/envs/science/lib/python3.6/site-packages/plotnine/facets/facet.py in eval_facet_vars(data, vars, env)
    637             res = data[name]
    638         else:
--> 639             res = env.eval(name, inner_namespace=data)
    640         facet_vals[name] = res
    641 

~/miniconda3/envs/science/lib/python3.6/site-packages/patsy/eval.py in eval(self, expr, source_name, inner_namespace)
    164         code = compile(expr, source_name, "eval", self.flags, False)
    165         return eval(code, {}, VarLookupDict([inner_namespace]
--> 166                                             + self._namespaces))
    167 
    168     @classmethod

<string> in <module>()

NameError: name 'a' is not defined

If the geom_abline call is removed, this works correctly. I think generally, if a variable isn't available to facet on, then any geoms with that variable missing should be plotted with all available data.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions