如何用Pandas和Altair实现时间块的正确排序与可视化?
高效解决时间块排序问题(Altair + Pandas)
当处理包含80多个15分钟间隔的时间块数据时,手动创建排序映射字典效率极低,可通过以下两种自动化方案解决Altair图表X轴排序混乱的问题:
方案一:Pandas自动生成排序列
通过解析时间块的起始时间,计算其相对于0点的分钟数作为排序依据,无需手动维护映射字典。对于跨午夜的时间块(如11:30 pm - 01:00 am),可通过调整排序值确保其排在当天所有时间段之后。
import pandas as pd import altair as alt # 示例数据(替换为你的实际数据) aggdf = pd.DataFrame({ 'Time': ['05:00 am - 09:00 am', '09:00 am - 12:00 pm', '12:00 pm - 03:00 pm', '03:00 pm - 05:00 pm', '05:00 pm - 07:00 pm', '07:00 pm - 11:00 pm', '11:00 pm - 11:30 pm', '11:30 pm - 01:00 am'], 'RTG': [2.3, 3.1, 2.7, 4.0, 3.5, 2.9, 1.8, 1.2], 'Station': ['A']*8 }) # 提取起始时间并转换为当日分钟数 def get_start_minutes(time_block): start_time_str = time_block.split(' - ')[0].strip() start_time = pd.to_datetime(start_time_str, format='%I:%M %p').time() return start_time.hour * 60 + start_time.minute aggdf['Order'] = aggdf['Time'].apply(get_start_minutes) # 标记跨午夜的时间块,调整排序值确保其排在当日末尾 def is_cross_midnight(time_block): start_str, end_str = time_block.split(' - ') start_time = pd.to_datetime(start_str.strip(), format='%I:%M %p').time() end_time = pd.to_datetime(end_str.strip(), format='%I:%M %p').time() return end_time < start_time aggdf.loc[aggdf['Time'].apply(is_cross_midnight), 'Order'] += 1440 # 1440为一天的分钟数 # Altair可视化指定排序 chart = alt.Chart(aggdf).mark_line(point=True).encode( x=alt.X('Time', sort=alt.Sort(field='Order', order='ascending')), y='RTG', color='Station' ) chart.show()
方案二:直接在Altair中解析排序(无需额外列)
利用Altair的表达式功能,直接在编码时解析时间块的起始时间,以此作为排序依据,省去Pandas生成排序列的步骤:
import pandas as pd import altair as alt # 示例数据(替换为你的实际数据) aggdf = pd.DataFrame({ 'Time': ['05:00 am - 09:00 am', '09:00 am - 12:00 pm', '12:00 pm - 03:00 pm', '03:00 pm - 05:00 pm', '05:00 pm - 07:00 pm', '07:00 pm - 11:00 pm', '11:00 pm - 11:30 pm', '11:30 pm - 01:00 am'], 'RTG': [2.3, 3.1, 2.7, 4.0, 3.5, 2.9, 1.8, 1.2], 'Station': ['A']*8 }) # 直接在Altair中通过表达式解析起始时间排序 chart = alt.Chart(aggdf).mark_line(point=True).encode( x=alt.X('Time', sort=alt.EncodingSortField( field='Time', op=alt.FieldOp( expr=""" let start = split(datum.Time, ' - ')[0]; parseDate(start, '%I:%M %p') """ ), order='ascending' )), y='RTG', color='Station' ) chart.show()
两种方案均能自动处理所有时间块的排序,无需手动创建映射字典,大幅提升效率。对于跨午夜的时间块,方案一通过调整分钟数确保排序正确,方案二则依赖时间解析后的自然顺序(当日23:30的时间值大于次日01:00,因此会排在末尾)。
内容的提问来源于stack exchange,提问作者Jack Driscoll
相关产品推荐
相关产品推荐

