Pandas、Bokeh 或使用任何绘图库移动季节性数据的 x 轴(7 月 -> 12 月 -> 6 月或 7 月 1 日 - 6 月 30 日)

Pandas, Bokeh, or using any plotting library for shifting the x-axis for seasonal data (months 7 -> 12 -> 6 or July 01 - June 30)

我想显示从 7 月 1 日到 6 月 30 日的季节性雪数据。

df = pd.DataFrame({'date1':['1954-03-20','1955-02-23','1956-01-01','1956-11-21','1958-01-07'],
               'date2':['1954-03-25','1955-02-26','1956-02-11','1956-11-30','1958-01-17']},
              index=['1954','1955','1956','1957','1958'])

这是我之前问题的延伸

Scott Boston 在回答我对该问题的评论时建议使用 Range1D 并修改 中的答案。它适用于连续标量,但我无法使其适用于 [182:366]、[1:181] 等不连续范围。

添加x_range=Range1d(182, 366) 显示了季节年的前半部分,但我无法得到季节年的下半部分(1, 181)。

df['date2'] = pd.to_datetime(df['date2'])

df['date1'] = pd.to_datetime(df['date1'])

df=df.assign(date2_DOY=df.date2.dt.dayofyear)
df=df.assign(date1_DOY=df.date1.dt.dayofyear)

from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import FuncTickFormatter, FixedTicker
p1 = figure(plot_width=1000, plot_height=300,x_range=Range1d(180, 366))

p1.circle(df.date1_DOY,df.index, color='red', legend='Date1')
p1.circle(df.date2_DOY,df.index, color='green', legend='Date2')
p1.xaxis[0].ticker=FixedTicker(ticks=[1,32,60,91,121,152,182,213,244,274,305,335,366])
p1.xaxis.formatter = FuncTickFormatter(code="""
 var labels = {'1':'Jan',32:'Feb',60:'Mar',91:'Apr',121:'May',152:'Jun',182:'Jul',213:'Aug',244:'Sep',274:'Oct',305:'Nov',335:'Dec',366:'Jan'}
 return labels[tick];
""")
show(p1)

#(Code from Scott's answer to my previous question.)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.DataFrame({'date1':['1954-03-20','1955-02-23','1956-01-01','1956-11-21','1958-01-07'],
               'date2':['1954-03-25','1955-02-26','1956-02-11','1956-11-30','1958-01-17']},
              index=['1954','1955','1956','1957','1958'])
df['date2'] = pd.to_datetime(df['date2'])

df['date1'] = pd.to_datetime(df['date1'])

从 6 月 1 日开始将年中的日期映射到轴。

df['date2_DOY_map'] = np.where(df['date2'].dt.dayofyear<151,df['date2'].dt.dayofyear-151+365,df['date2'].dt.dayofyear-151)

df['date1_DOY_map'] = np.where(df['date1'].dt.dayofyear<151,df['date1'].dt.dayofyear-151+365,df['date1'].dt.dayofyear-151)

from bokeh.plotting import figure, show
from bokeh.io import output_notebook

添加 Range1d 导入表单 bokeh.models

from bokeh.models import FuncTickFormatter, FixedTicker,Range1d
p1 = figure(plot_width=1000, plot_height=300,x_range=Range1d(1, 366))

p1.circle(df.date1_DOY_map,df.index, color='red', legend='Date1')
p1.circle(df.date2_DOY_map,df.index, color='green', legend='Date2')

修复了 x-ticks 和标签以匹配 6 月 1 日开始

p1.xaxis[0].ticker=FixedTicker(ticks=[1,31,62,93,123,154,184,215,246,274,305,335,366])
p1.xaxis.formatter = FuncTickFormatter(code="""
 var labels = {'1':'Jun',31:'Jul',62:'Aug',93:'Sep',123:'Oct',154:'Nov',184:'Dec',215:'Jan',246:'Feb',274:'Mar',305:'Apr',335:'May',366:'Jun'}
 return labels[tick];
""")
show(p1)

编辑(糟糕,我在上面的错误月份开始了)

很容易修复,我们只需要修改日期的 x 轴映射并重做刻度和标签。

使用 181 和 151,因为 7 月 1 日是第 181 天,而 6 月 1 日是第 151 天。

df['date2_DOY_map'] = np.where(df['date2'].dt.dayofyear<181,df['date2'].dt.dayofyear-181+365,df['date2'].dt.dayofyear-181)

df['date1_DOY_map'] = np.where(df['date1'].dt.dayofyear<181,df['date1'].dt.dayofyear-181+365,df['date1'].dt.dayofyear-181)

p1.xaxis[0].ticker=FixedTicker(ticks=[1,32,63,93,124,154,185,216,244,275,305,336,366])
p1.xaxis.formatter = FuncTickFormatter(code="""
 var labels = {'1':'Jul',32:'Aug',63:'Sep',93:'Oct',124:'Nov',154:'Dec',185:'Jan',216:'Feb',244:'Mar',275:'Apr',305:'May',336:'Jun',366:'Jul'}
 return labels[tick];
""")