RobinL
RobinL

Reputation: 11557

Multi view chart that shares data at the top level in Altair

How can we create multi-view charts which share data at the top level in Altair?

For example, how do we avoid the following situation, in which the dataset is repeated twice in the spec:

import altair as alt
import pandas as pd
data = pd.DataFrame({'x': [1.1, 2.5, 3.2], 'y': [0.8, 1.1, 2.7]})
c1 = alt.Chart(data).mark_point().encode(x='y', y='x')
c2 = alt.Chart(data).mark_bar().encode(x='y', y='x')
chart = c1 | c2

Upvotes: 1

Views: 305

Answers (2)

jakevdp
jakevdp

Reputation: 86310

As other answers mentioned, the current best pattern for this is to specify the data directly in the top-level chart. For example:

base = alt.Chart().encode(x='x', y='y')
chart = alt.hconcat(
    base.mark_point(),
    base.mark_bar(),
    data=data
)

A similar pattern can be used with alt.vconcat and alt.layer.

In Altair version 2.2 (which is not yet released as of this posting) there is a built-in way to automatically move all data to the top level, which you can read about in the associated pull request. If you run the following code during your session:

alt.data_transformers.consolidate_datasets = True

then each unique dataset used in your chart will be specified only once at the top level, even if it is referenced multiple times within the chart:

import altair as alt
import pandas as pd

print(alt.__version__)  # 2.2.0dev0

alt.data_transformers.consolidate_datasets = True

data = pd.DataFrame({'x': [1.1, 2.5, 3.2], 'y': [0.8, 1.1, 2.7]})
base = alt.Chart(data).encode(x='y', y='x')
chart = base.mark_bar() | base.mark_point()
print(chart.to_dict())

# {'$schema': 'https://vega.github.io/schema/vega-lite/v2.5.2.json',
#  'config': {'view': {'height': 300, 'width': 400}},
#  'datasets': {'data-3a2675f17784b0259a9c377073f400f2': [{'x': 1.1, 'y': 0.8},
#    {'x': 2.5, 'y': 1.1},
#    {'x': 3.2, 'y': 2.7}]},
#  'hconcat': [{'data': {'name': 'data-3a2675f17784b0259a9c377073f400f2'},
#    'encoding': {'x': {'field': 'y', 'type': 'quantitative'},
#     'y': {'field': 'x', 'type': 'quantitative'}},
#    'mark': 'bar'},
#   {'data': {'name': 'data-3a2675f17784b0259a9c377073f400f2'},
#    'encoding': {'x': {'field': 'y', 'type': 'quantitative'},
#     'y': {'field': 'x', 'type': 'quantitative'}},
#    'mark': 'point'}]}

There is currently a discussion about whether this should be the default behavior; see https://github.com/altair-viz/altair/issues/981. I'm leaning heavily toward yes, but am a bit concerned about breaking things in corner cases.

Upvotes: 2

RobinL
RobinL

Reputation: 11557

We can use the top-level objects HConcatChart, VConcatChart, and LayerChart.

An example is as follows:

import altair as alt
import pandas as pd
data = pd.DataFrame({'x': [1.1, 2.5, 3.2], 'y': [0.8, 1.1, 2.7]})
c1 = alt.Chart().mark_point().encode(x='y', y='x')
c2 = alt.Chart().mark_bar().encode(x='y', y='x')
chart = alt.HConcatChart(data, hconcat=[c1,c2])

Upvotes: 0

Related Questions