在Colab中使用Altair绘制日均温图时的截断异常问题
解决Altair绘制全球温度图时365天处的截断异常
我尝试用Altair复刻Climate Reanalyzer网站的全球温度图,数据加载流程如下:
import pandas as pd import altair as alt import json import requests # 补充原代码缺失的导入 url = "https://climatereanalyzer.org/clim/t2_daily/json/era5_world_t2_day.json" data = requests.get(url).json() years = [] all_temperatures = [] for year_data in data: year = year_data['name'] temperatures = year_data['data'] temperatures = [temp if temp is not None else float('nan') for temp in temperatures] days = list(range(1, len(temperatures) + 1)) df = pd.DataFrame({ 'Year': [year] * len(temperatures), 'Day': days, 'Temperature': temperatures }) years.append(year) all_temperatures.append(df) df_all = pd.concat(all_temperatures)
绘图时遇到365天处的截断异常:多条曲线在年末突然向x轴365位置聚拢,形成明显的异常痕迹。当前绘图代码如下:
alt.data_transformers.enable('default', max_rows=None) chart = alt.Chart(df_all).mark_line().encode( x=alt.X( 'Day:Q', title='Day of the Year', scale=alt.Scale(domain=(0, 365), clamp=True)), y=alt.Y( 'Temperature:Q', title='Temperature (°C)', scale=alt.Scale(domain=(11, 18), clamp=True)), ).properties( title='Daily World Temperatures', width=600, height=600 ).encode( color=alt.Color( 'Year:N', legend=alt.Legend( orient='bottom', columns=10, symbolLimit=100 ) ), ) chart
问题原因
异常源于闰年数据的处理冲突:部分年份是闰年,包含366天的数据,但x轴被设置为domain=(0,365)且开启了clamp=True,这会将所有超过365的天数强制映射到365的位置,导致闰年第366天的温度点全部叠加在x=365处,形成线条聚拢的异常。
解决方案
方案1:扩展x轴范围容纳闰年数据
调整x轴的domain为(0,366),让闰年的366天数据正常显示,避免截断:
alt.data_transformers.enable('default', max_rows=None) chart = alt.Chart(df_all).mark_line().encode( x=alt.X( 'Day:Q', title='Day of the Year', scale=alt.Scale(domain=(0, 366), clamp=True), # 修改domain范围 axis=alt.Axis(values=list(range(0, 367, 30))) # 可选:设置刻度间隔,避免过密 ), y=alt.Y( 'Temperature:Q', title='Temperature (°C)', scale=alt.Scale(domain=(11, 18), clamp=True)), color=alt.Color( 'Year:N', legend=alt.Legend( orient='bottom', columns=10, symbolLimit=100 ) ), ).properties( title='Daily World Temperatures', width=600, height=600 ) chart
方案2:预处理数据移除闰年第366天
如果不需要保留闰年最后一天的数据,可以在数据加载阶段过滤掉:
# 在生成days和temperatures后添加过滤逻辑 # 只保留前365天的数据 temperatures = temperatures[:365] days = days[:365]
修改后再执行后续的DataFrame创建,这样所有年份都统一为365天,x轴设置(0,365)就不会有截断问题。
内容的提问来源于stack exchange,提问作者Don
相关产品推荐
相关产品推荐

