选择详情#
此示例展示了一个连接两种数据视图的选择:左侧面板包含每个对象一个点,右侧面板包含每个对象一条线。点击点或线都会在两种数据视图中选择相应的对象。
挑战在于如何以 Altair 可以处理的方式表达这种分层数据。我们通过将数据合并为“长格式”数据帧,并聚合最终绘图的相同元数据来实现这一点。
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'])
color = (
alt.when(selector)
.then(alt.Color("id:O").legend(None))
.otherwise(alt.value("lightgray"))
)
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=color,
)
line = 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 | line
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'])
color = (
alt.when(selector)
.then(alt.Color("id:O", legend=None))
.otherwise(alt.value("lightgray"))
)
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=color,
)
line = 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 | line