我有一个包含列的数据框:'sex'、'urb'、'age'、'time'、'value'。
我需要从“sex”和“urb”中选择一个元素,从“age”列中选择多个元素,然后制作一个交互式折线图,x 轴为“时间”,y 为“值”,图例中为年龄。
我将 selection_multi() 添加到每个 'sex'、'urb' 和 'age' 列的单独 mark_rect(例如 y='sex:O',没有 x 轴)。
我希望 mark_line() 能够基于 selection_multi() 绘制线条。例如,如果我选择:
- 来自“性”的“男性”
- '城市' 来自 'urb'
- “年龄”中的“20 多岁”和“40 多岁”
然后2行:
- 男 - 城市 - 20 多岁
- 男性 - 城市 - 40 多岁
绘制。
但是,选择不像我预期的那样工作。例如,如果我从“sex”mark_rect() 中选择“Male”,从“urb”mark_rect() 中选择“Urban”,那么在“sex”mark_rect() 中会自动选择“Female”。无法选择“男性”和“城市”,即使数据框中有“男性”和“城市”的行。
我究竟做错了什么?
import altair as alt
import pandas as pd
import itertools as it
levels = it.product(['Male', 'Female'], ['Urban', 'Rural'], ['20s', '30s', '40s'], ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'])
data = pd.DataFrame(list(levels), columns=['sex', 'urb', 'age', 'time'])
data['value'] = [x for x in range(1, 13) for y in range(6)]
selector = alt.selection_multi(fields=['sex', 'urb', 'age'])
ax = alt.Axis(offset=-60, orient='right', domain=False, ticks=False, title=None)
clr = alt.condition(selector, alt.value('lightblue'), alt.value('lightgray'), legend=None)
sex = alt.Chart(data, title='sex (single selection)').mark_rect().encode(y=alt.Y('sex:N', axis=ax), color=clr).properties(width=60, height=40).add_selection(selector)
urb = alt.Chart(data, title='urb (single selection)').mark_rect().encode(y=alt.Y('urb:N', axis=ax), color=clr).properties(width=60, height=40).add_selection(selector)
age = alt.Chart(data, title='age (multi selection) ').mark_rect().encode(y=alt.Y('age:N', axis=ax), color=clr).properties(width=60, height=60).add_selection(selector)
line = alt.Chart(data).mark_line().encode(x='time:O', y='value:Q', color='age:O').transform_filter(selector).properties(width=200, height=200)
sex_urb = alt.Chart(data).mark_rect().encode(x='sex:O', y='urb:O').transform_filter(selector).properties(width=40, height=40)
sex_age = alt.Chart(data).mark_rect().encode(x='sex:O', y='age:O').transform_filter(selector).properties(width=40, height=40)
urb_age = alt.Chart(data).mark_rect().encode(x='urb:O', y='age:O').transform_filter(selector).properties(width=40, height=40)
sex_urb_base = alt.Chart(data).mark_rect().encode(x='sex:O', y='urb:O', color=alt.value('white')).properties(width=40, height=40)
sex_age_base = alt.Chart(data).mark_rect().encode(x='sex:O', y='age:O', color=alt.value('white')).properties(width=40, height=40)
urb_age_base = alt.Chart(data).mark_rect().encode(x='urb:O', y='age:O', color=alt.value('white')).properties(width=40, height=40)
alt.hconcat(alt.vconcat(sex, urb, age), alt.vconcat(sex_urb_base + sex_urb, sex_age_base + sex_age, urb_age_base + urb_age), line)