Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine text and data charts with facet?

Tags:

python

altair

I'm working off the code in this example, slightly modified:

https://altair-viz.github.io/gallery/layered_heatmap_text.html

I'm trying to figure out why the my code breaks when I try to facet into columns.

# Import data
import altair as alt
from vega_datasets import data

source = data.cars()

# Configure common options
base = alt.Chart(source)
scale = alt.Scale(paddingInner=0)

The original version works fine:

# Configure heatmap
heatmap = base.mark_rect().encode(
    alt.X('Cylinders:O', scale=scale),
    alt.Y('Year:O', scale=scale),
    color='count()'
)

# Configure text
text = base.mark_text(baseline='middle').encode(
    x='Cylinders:O',
    y='Year:O',
    text='count()',
    color=alt.value('white')
)

# Draw the chart
heatmap+text

Now I would like to facet by Origin. The code below works when I display heatmap and text separately, but when I combine them, I get an error.

# Configure heatmap
heatmap = base.mark_rect().encode(
    alt.X('Cylinders:O', scale=scale),
    alt.Y('Year:O', scale=scale),
    color='count()',
    column = 'Origin'
)

# Configure text
text = base.mark_text(baseline='middle').encode(
    x='Cylinders:O',
    y='Year:O',
    text='count()',
    color=alt.value('white'),
    column = 'Origin'
)

# Draw the chart
heatmap+text

Here's the error message - I'm not really understanding where the issue is stemming from.

---------------------------------------------------------------------------
SchemaValidationError                     Traceback (most recent call last)
~/miniconda3/lib/python3.6/site-packages/altair/vegalite/v2/api.py in _repr_mimebundle_(self, include, exclude)
   1111         try:
-> 1112             dct = self.to_dict()
   1113         except Exception:

~/miniconda3/lib/python3.6/site-packages/altair/vegalite/v2/api.py in to_dict(self, *args, **kwargs)
    420             kwargs['validate'] = 'deep'
--> 421             dct = super(TopLevelMixin, copy).to_dict(*args, **kwargs)
    422 

~/miniconda3/lib/python3.6/site-packages/altair/utils/schemapi.py in to_dict(self, validate, ignore, context)
    253             except jsonschema.ValidationError as err:
--> 254                 raise SchemaValidationError(self, err)
    255         return result

<class 'str'>: (<class 'TypeError'>, TypeError('sequence item 1: expected str instance, int found',))

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
~/miniconda3/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude)
    968 
    969             if method is not None:
--> 970                 return method(include=include, exclude=exclude)
    971             return None
    972         else:

~/miniconda3/lib/python3.6/site-packages/altair/vegalite/v2/api.py in _repr_mimebundle_(self, include, exclude)
   1112             dct = self.to_dict()
   1113         except Exception:
-> 1114             utils.display_traceback(in_ipython=True)
   1115             return {}
   1116         else:

~/miniconda3/lib/python3.6/site-packages/altair/utils/core.py in display_traceback(in_ipython)
    403 
    404     if ip is not None:
--> 405         ip.showtraceback(exc_info)
    406     else:
    407         traceback.print_exception(*exc_info)

~/miniconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py in showtraceback(self, exc_tuple, filename, tb_offset, exception_only, running_compiled_code)
   2036                                             value, tb, tb_offset=tb_offset)
   2037 
-> 2038                     self._showtraceback(etype, value, stb)
   2039                     if self.call_pdb:
   2040                         # drop into debugger

~/miniconda3/lib/python3.6/site-packages/ipykernel/zmqshell.py in _showtraceback(self, etype, evalue, stb)
    544             u'traceback' : stb,
    545             u'ename' : unicode_type(etype.__name__),
--> 546             u'evalue' : py3compat.safe_unicode(evalue),
    547         }
    548 

~/miniconda3/lib/python3.6/site-packages/ipython_genutils/py3compat.py in safe_unicode(e)
     63     """
     64     try:
---> 65         return unicode_type(e)
     66     except UnicodeError:
     67         pass

~/miniconda3/lib/python3.6/site-packages/altair/utils/schemapi.py in __unicode__(self)
     67         schema_path = ['{}.{}'.format(cls.__module__, cls.__name__)]
     68         schema_path.extend(self.schema_path)
---> 69         schema_path = '->'.join(val for val in schema_path[:-1]
     70                                 if val not in ('properties',
     71                                                'additionalProperties',

TypeError: sequence item 1: expected str instance, int found
like image 492
max Avatar asked Jan 26 '23 15:01

max


1 Answers

The issue is that faceted charts cannot be layered (this is because in general, there is no guarantee that the two layers will have compatible facets). On the other hand, layered charts can be faceted. For example:

# Import data
import altair as alt
from vega_datasets import data

source = data.cars()

# Configure common options
scale = alt.Scale(paddingInner=0)

# Configure heatmap
heatmap = alt.Chart().mark_rect().encode(
    alt.X('Cylinders:O', scale=scale),
    alt.Y('Year:O', scale=scale),
    color='count()'
)

# Configure text
text = alt.Chart().mark_text(baseline='middle').encode(
    x='Cylinders:O',
    y='Year:O',
    text='count()',
    color=alt.value('white')
)

# Draw the chart.
alt.layer(heatmap, text, data=source).facet(
    column='Origin'
)

enter image description here

Note that when using this approach, it's important to specify the data at the level of the facet rather than in the child layers. For more information, see Faceted Charts in the Altair docs.

The error message here used to be more helpful... it seems that the jsonschema library is reporting schema validation errors differently than it used to.

like image 86
jakevdp Avatar answered Jan 29 '23 06:01

jakevdp