From cff40e30bf5d487088a3f6377e2610ecfb1016bd Mon Sep 17 00:00:00 2001 From: Jake VanderPlas Date: Thu, 11 Nov 2021 19:59:05 -0800 Subject: [PATCH] Inject empty data into alt.Chart for easier datum encodings --- altair/examples/line_chart_with_datum.py | 7 +++---- altair/examples/pacman_chart.py | 4 +--- altair/vegalite/v4/api.py | 15 ++++++++++++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/altair/examples/line_chart_with_datum.py b/altair/examples/line_chart_with_datum.py index e568b3e65..490bd0dcc 100644 --- a/altair/examples/line_chart_with_datum.py +++ b/altair/examples/line_chart_with_datum.py @@ -11,22 +11,21 @@ from vega_datasets import data source = data.stocks() -no_source = alt.Data(values=[{}]) lines = ( alt.Chart(source) .mark_line() - .encode(x=alt.X("date"), y=alt.Y("price"), color="symbol") + .encode(x="date", y="price", color="symbol") ) xrule = ( - alt.Chart(no_source) + alt.Chart() .mark_rule(color="cyan", strokeWidth=2) .encode(x=alt.datum(alt.DateTime(year=2006, month="November"))) ) yrule = ( - alt.Chart(no_source).mark_rule(strokeDash=[12, 6], size=2).encode(y=alt.datum(350)) + alt.Chart().mark_rule(strokeDash=[12, 6], size=2).encode(y=alt.datum(350)) ) diff --git a/altair/examples/pacman_chart.py b/altair/examples/pacman_chart.py index 850c986b7..0058acd7b 100644 --- a/altair/examples/pacman_chart.py +++ b/altair/examples/pacman_chart.py @@ -10,9 +10,7 @@ import numpy as np import altair as alt -no_source = alt.Data(values=[{}]) - -alt.Chart(no_source).mark_arc(color="gold").encode( +alt.Chart().mark_arc(color="gold").encode( theta=alt.datum((5 / 8) * np.pi, scale=None), theta2=alt.datum((19 / 8) * np.pi), radius=alt.datum(100, scale=None), diff --git a/altair/vegalite/v4/api.py b/altair/vegalite/v4/api.py index 572316412..84162e114 100644 --- a/altair/vegalite/v4/api.py +++ b/altair/vegalite/v4/api.py @@ -32,6 +32,8 @@ def _dataset_name(values): """ if isinstance(values, core.InlineDataset): values = values.to_dict() + if values == [{}]: + return "empty" values_json = json.dumps(values, sort_keys=True) hsh = hashlib.md5(values_json.encode()).hexdigest() return "data-" + hsh @@ -109,7 +111,7 @@ def _prepare_data(data, context=None): @utils.use_signature(core.LookupData) class LookupData(core.LookupData): def to_dict(self, *args, **kwargs): - """Convert the chart to a dictionary suitable for JSON export""" + """Convert the chart to a dictionary suitable for JSON export.""" copy = self.copy(deep=False) copy.data = _prepare_data(copy.data, kwargs.get("context")) return super(LookupData, copy).to_dict(*args, **kwargs) @@ -2006,6 +2008,17 @@ def from_dict(cls, dct, validate=True): # As a last resort, try using the Root vegalite object return core.Root.from_dict(dct, validate) + def to_dict(self, *args, **kwargs): + """Convert the chart to a dictionary suitable for JSON export.""" + context = kwargs.get("context", {}) + if self.data is Undefined and "data" not in context: + # No data specified here or in parent: inject empty data + # for easier specification of datum encodings. + copy = self.copy(deep=False) + copy.data = core.InlineData(values=[{}]) + return super(Chart, copy).to_dict(*args, **kwargs) + return super().to_dict(*args, **kwargs) + def add_selection(self, *selections): """Add one or more selections to the chart.""" if not selections: