Skip to content

Commit

Permalink
More notes and structrue ... maybe types?
Browse files Browse the repository at this point in the history
  • Loading branch information
mwaskom committed May 17, 2021
1 parent 4e29433 commit 1440647
Showing 1 changed file with 67 additions and 28 deletions.
95 changes: 67 additions & 28 deletions seaborn/_new_core.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
from __future__ import annotations
from pandas import DataFrame


class Plot:

def __init__(self, data=None, **variables):

# Note that we can't assume wide-form here if variables does not contain x or y
# because those might get assigned in long-form fashion per layer.

self.data = DataSource(data, variables)
self.layers = []

def add(self, mark, stat=None, data=None, variables=None):
def add(
self,
mark: Mark,
stat: Stat = None,
data: DataFrame = None,
variables: dict[str, str] = None,
):

# TODO what if in wide-form mode, we convert to long-form
# based on the transform that mark defines?
Expand All @@ -24,6 +35,24 @@ def plot(self):
for layer in self.layers:
layer.plot()

def _plot_layer(self):

# Roughly ...

# TODO where does this method come from?
data = self.as_numeric(self.data)

# TODO who owns the groupby logic?
data = self.stat(data)

# Our statistics happen on the scale we want, but then matplotlib is going
# to re-handle the scaling, so we need to invert before handing off
# Note: we don't need to convert back to strings for categories (but we could?)
data = self.invert_scale(data)

# Something like this?
self.mark.plot(data) # do we pass ax (and/or facets?! here?)

def show(self):

# TODO guard this here?
Expand All @@ -42,48 +71,46 @@ def _repr_html_(self):
pass


class Layer:

def __init__(self, data, mark, stat):

self.data = data
self.mark = mark
self.stat = stat

def plot(self):

# Do we need this method, or can Plot just have a plot_layer method that
# each entry in the layers list gets passed to? (Meaning that Layer would just
# be a simple Dataclass or similar?

# Roughly ...
# Do we want some sort of generator that yields a tuple of (semantics, data,
# axes), or similar? I guess this is basically the existing iter_data, although
# currently the logic of getting the relevant axes lives externally (but makes
# more sense within the generator logic). Where does this iteration happen? I
# think we pass the generator into the Mark.plot method? Currently the plot_*
# methods define their own grouping variables. So I guess we need to delegate to
# them. But maybe that could be an attribute on the mark? (Same deal for the
# stat?)

# TODO where does this method come from?
data = self.as_numeric(self.data)

# TODO who owns the groupby logic?
data = self.stat(data)
class DataSource:

# Our statistics happen on the scale we want, but then matplotlib is going
# to re-handle the scaling, so we need to invert before handing off
# Note: we don't need to convert back to strings for categories (but we could?)
data = self.invert_scale(data)
# How to handle wide-form data here, when the dimensional semantics are defined by
# the mark? (I guess? that will be most consistent with how it currently works.)
# I think we want to avoid too much deferred execution or else tracebacks are going
# to be confusing to follow...

# Something like this?
self.mark.plot(data) # do we pass ax (and/or facets?! here?)
# With wide-form data, should we allow marks with distinct wide_form semantics?
# I think in most cases that will not make sense? When to check?

# I guess more generally, what to do when different variables are assigned in
# different calls to Plot.add()? This has to be possible (otherwise why allow it)?
# What does ggplot do here?

class DataSource:
# Who owns the existing VectorPlotter.variables, VectorPlotter.var_levels, etc.?

def __init__(self, data, variables):

pass

def join(self, other):
def join(self, other: DataSource):

pass


class Stat:

pass


class Mark:

pass
Expand All @@ -95,3 +122,15 @@ def plot(self):

# TODO how do we end up with ax, data, etc?
pass


class Layer:

# Does this need to be anything other than a simple container for these attributes?
# Could use a Dataclass I guess?

def __init__(self, data: DataSource, mark: Mark, stat: Stat):

self.data = data
self.mark = mark
self.stat = stat

0 comments on commit 1440647

Please sign in to comment.