:orphan: :html_theme.sidebar_secondary.remove: .. This document is auto-generated by the altair-gallery extension. Do not modify directly. .. _gallery_select_detail: Selection Detail ================ This example shows a selection that links two views of data: the left panel contains one point per object, and the right panel contains one line per object. Clicking on either the points or lines will select the corresponding objects in both views of the data. The challenge lies in expressing such hierarchical data in a way that Altair can handle. We do this by merging the data into a "long form" dataframe, and aggregating identical metadata for the final plot. .. altair-plot:: :remove-code: import altair as alt import pandas as pd import numpy as np np.random.seed(0) n_objects = 20 n_times = 50 # Create one (x, y) pair of metadata per object locations = pd.DataFrame({ 'id': range(n_objects), 'x': np.random.randn(n_objects), 'y': np.random.randn(n_objects) }) # Create a 50-element time-series for each object timeseries = pd.DataFrame(np.random.randn(n_times, n_objects).cumsum(0), columns=locations['id'], index=pd.RangeIndex(0, n_times, name='time')) # Melt the wide-form timeseries into a long-form view timeseries = timeseries.reset_index().melt('time') # Merge the (x, y) metadata into the long-form view timeseries['id'] = timeseries['id'].astype(int) # make merge not complain data = pd.merge(timeseries, locations, on='id') # Data is prepared, now make a chart selector = alt.selection_point(fields=['id']) base = alt.Chart(data).properties( width=250, height=250 ).add_params(selector) points = base.mark_point(filled=True, size=200).encode( x='mean(x)', y='mean(y)', color=alt.condition(selector, 'id:O', alt.value('lightgray'), legend=None), ) timeseries = base.mark_line().encode( x='time', y=alt.Y('value', scale=alt.Scale(domain=(-15, 15))), color=alt.Color('id:O', legend=None) ).transform_filter( selector ) points | timeseries .. tab-set:: .. tab-item:: Method syntax :sync: method .. code:: python import altair as alt import pandas as pd import numpy as np np.random.seed(0) n_objects = 20 n_times = 50 # Create one (x, y) pair of metadata per object locations = pd.DataFrame({ 'id': range(n_objects), 'x': np.random.randn(n_objects), 'y': np.random.randn(n_objects) }) # Create a 50-element time-series for each object timeseries = pd.DataFrame(np.random.randn(n_times, n_objects).cumsum(0), columns=locations['id'], index=pd.RangeIndex(0, n_times, name='time')) # Melt the wide-form timeseries into a long-form view timeseries = timeseries.reset_index().melt('time') # Merge the (x, y) metadata into the long-form view timeseries['id'] = timeseries['id'].astype(int) # make merge not complain data = pd.merge(timeseries, locations, on='id') # Data is prepared, now make a chart selector = alt.selection_point(fields=['id']) base = alt.Chart(data).properties( width=250, height=250 ).add_params(selector) points = base.mark_point(filled=True, size=200).encode( x='mean(x)', y='mean(y)', color=alt.condition(selector, 'id:O', alt.value('lightgray'), legend=None), ) timeseries = base.mark_line().encode( x='time', y=alt.Y('value').scale(domain=(-15, 15)), color=alt.Color('id:O').legend(None) ).transform_filter( selector ) points | timeseries .. tab-item:: Attribute syntax :sync: attribute .. code:: python import altair as alt import pandas as pd import numpy as np np.random.seed(0) n_objects = 20 n_times = 50 # Create one (x, y) pair of metadata per object locations = pd.DataFrame({ 'id': range(n_objects), 'x': np.random.randn(n_objects), 'y': np.random.randn(n_objects) }) # Create a 50-element time-series for each object timeseries = pd.DataFrame(np.random.randn(n_times, n_objects).cumsum(0), columns=locations['id'], index=pd.RangeIndex(0, n_times, name='time')) # Melt the wide-form timeseries into a long-form view timeseries = timeseries.reset_index().melt('time') # Merge the (x, y) metadata into the long-form view timeseries['id'] = timeseries['id'].astype(int) # make merge not complain data = pd.merge(timeseries, locations, on='id') # Data is prepared, now make a chart selector = alt.selection_point(fields=['id']) base = alt.Chart(data).properties( width=250, height=250 ).add_params(selector) points = base.mark_point(filled=True, size=200).encode( x='mean(x)', y='mean(y)', color=alt.condition(selector, 'id:O', alt.value('lightgray'), legend=None), ) timeseries = base.mark_line().encode( x='time', y=alt.Y('value', scale=alt.Scale(domain=(-15, 15))), color=alt.Color('id:O', legend=None) ).transform_filter( selector ) points | timeseries