Matplotlib时间序列箱线图中设置X轴主刻度的问题
Matplotlib时间序列箱线图中设置X轴主刻度的问题
嘿,我知道你遇到的这个X轴突然显示1970年的问题了,这其实是seaborn箱线图处理日期轴的小坑导致的,我来帮你捋清楚并解决它~
问题根源
你原来的代码里,直接用df['Date']作为x轴绘制箱线图时,seaborn会把每个不同的日期都当作独立的类别,而不是把x轴当作连续的时间轴。这时候x轴的底层数值其实是类别的索引(0、1、2……),而非日期对应的时间戳。当你用mdates.MonthLocator这类日期定位器时,它会把这些索引值当成时间戳来解析——0对应的就是Unix纪元起始点1970-01-01,所以就出现了奇怪的1970年标签。
解决方案
我们有两种实用的思路来解决这个问题,根据你的数据跨度和需求选择就行:
思路1:按年月分组生成箱线图(适合短时间跨度)
直接给数据新增一个“年月”列,用这个列作为x轴绘制箱线图,手动控制标签显示:
import matplotlib.pyplot as plt import seaborn as sns import pandas as pd import random # 生成原始数据 Dates = pd.date_range(start="2020-01-01", end="2020-02-15", freq='D').date data = {'Date': [], 'Values': []} for d in Dates: data['Date'].extend([d] * 10) data['Values'].extend(random.sample(range(1, 101), 10)) df = pd.DataFrame(data) df['Date'] = pd.to_datetime(df['Date']) # 新增年月列,格式为"月 年"(比如Jan 2020) df['Month_Year'] = df['Date'].dt.strftime('%b %Y') # 基于年月列绘制箱线图 sns.boxplot(x='Month_Year', y='Values', data=df) plt.xticks(rotation=45) plt.title('Time Series Box Plot') plt.ylabel('Values') plt.xlabel('Date') plt.tight_layout() plt.show()
思路2:将x轴设为连续日期轴(适合长时间跨度,支持间隔刻度)
如果你的数据跨度多年,想要灵活设置每N个月显示一次刻度,可以把每个日期转换为当月第一天,让x轴成为连续的时间轴,再用matplotlib的日期工具控制刻度:
import matplotlib.pyplot as plt import seaborn as sns import pandas as pd import matplotlib.dates as mdates import random # 生成跨多年的测试数据 Dates = pd.date_range(start="2020-01-01", end="2022-02-15", freq='D').date data = {'Date': [], 'Values': []} for d in Dates: data['Date'].extend([d] * 10) data['Values'].extend(random.sample(range(1, 101), 10)) df = pd.DataFrame(data) df['Date'] = pd.to_datetime(df['Date']) # 将每个日期转换为当月第一天,作为箱线图的分组依据 df['Month_Start'] = df['Date'].dt.to_period('M').dt.start_time # 基于当月第一天绘制箱线图,此时x轴是连续时间轴 ax = sns.boxplot(x='Month_Start', y='Values', data=df) plt.xticks(rotation=45) plt.title('Time Series Box Plot') plt.ylabel('Values') plt.xlabel('Date') # 设置每2个月显示一个刻度,格式为"月 年" ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2)) ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y')) plt.tight_layout() plt.show()
这两种方法都能完美解决你遇到的1970年刻度问题,同时满足你只显示月份和年份、控制刻度间隔的需求~
备注:内容来源于stack exchange,提问作者yippie
相关产品推荐
相关产品推荐

