Altair图表:如何为指定年份子集生成精简图例?
气候温度折线图复刻与图例优化方案
核心需求
- 将1940-2022年的温度折线设为灰色低透明度,2023年设为红色,2024年设为黑色
- 图例仅显示三个分组:
1940-2022、2023、2024(或可选择仅保留2023和2024) - 优化代码结构与运行效率
图例实现核心思路
通过创建分组标签列替代原有的手动颜色/透明度列,让Altair自动基于分组生成精简图例:
- 新增
LegendGroup列,将年份按需求分为三个类别 - 直接在Altair编码中绑定该分组列,指定颜色、透明度、线宽的映射规则
- 保留图例显示,自动展示分组标签
代码优化建议
- 用pandas向量化操作替代
apply循环,提升数据处理效率 - 简化日期标签生成逻辑,避免手动构建字典
- 修复依赖缺失(补充
requests导入) - 移除冗余的手动生成列(如
Color、Opacity),直接通过Altair编码实现样式映射
完整修改后代码
import pandas as pd import altair as alt import requests # 补充缺失的依赖导入 # 数据获取与预处理 def fetch_and_prep_data(): url = "https://climatereanalyzer.org/clim/t2_daily/json/era5_world_t2_day.json" data = requests.get(url).json() all_dfs = [] for year_data in data: year = year_data['name'] # 过滤非4位数字年份 if len(year) != 4: continue temperatures = [temp if temp is not None else float('nan') for temp in year_data['data']] days = list(range(1, len(temperatures)+1)) df = pd.DataFrame({ 'Year': [int(year)]*len(temperatures), # 直接转换为整数 'Day': days, 'Temperature': temperatures }) all_dfs.append(df) df_at = pd.concat(all_dfs) # 新增分组列,用于图例与样式映射 df_at['LegendGroup'] = pd.cut( df_at['Year'], bins=[0, 2022, 2023, 2024], labels=['1940-2022', '2023', '2024'], include_lowest=True ) # 过滤无效天数 df_at = df_at[df_at['Day'] <= 365] return df_at # 生成x轴月份标签(每月最后一天的日序与缩写) def get_month_labels(): dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D') last_days = dates[dates.is_month_end] return last_days.day_of_year.tolist(), last_days.strftime('%b').tolist() # 主绘图逻辑 df = fetch_and_prep_data() tick_values, tick_labels = get_month_labels() line_chart = alt.Chart(df).mark_line().encode( x=alt.X( 'Day:Q', title='Month', scale=alt.Scale(domain=(0, 365), clamp=True), axis=alt.Axis( tickCount=12, values=tick_values, labels=True, # 动态匹配标签与刻度值 labelExpr="indexof(values, datum.value) > -1 ? labels[indexof(values, datum.value)] : ''", labelOffset=-30 ) ), y=alt.Y( 'Temperature:Q', title='Temperature (°C)', scale=alt.Scale(domain=(11, 18), clamp=True) ), # 基于分组列映射颜色,自动生成图例 color=alt.Color( 'LegendGroup:N', scale=alt.Scale( domain=['1940-2022', '2023', '2024'], range=['gray', 'red', 'black'] ), title='Year Group' ), # 分组映射透明度 opacity=alt.Opacity( 'LegendGroup:N', scale=alt.Scale( domain=['1940-2022', '2023', '2024'], range=[0.01, 1.0, 1.0] ), legend=None ), # 分组映射线宽 strokeWidth=alt.StrokeWidth( 'LegendGroup:N', scale=alt.Scale( domain=['1940-2022', '2023', '2024'], range=[1, 4, 4] ), legend=None ), # 按年份拆分折线,避免合并 detail='Year:N' ).properties( width=800, height=600 ) line_chart
可选:仅保留2023和2024的图例
若需要隐藏1940-2022的图例项,可在颜色编码中添加legend=alt.Legend(values=['2023', '2024']):
color=alt.Color( 'LegendGroup:N', scale=alt.Scale( domain=['1940-2022', '2023', '2024'], range=['gray', 'red', 'black'] ), title='Year', legend=alt.Legend(values=['2023', '2024']) # 仅显示指定图例项 )
内容的提问来源于stack exchange,提问作者Don
相关产品推荐
相关产品推荐

