Can I create a time series with a reverse-log axis scale, so more recent dates are wider apart?
Question:
In a few recent applications I have plotted some time series where the more recent values are of more interest, but the historical values are good for context. Here’s an example, a toy tracker for progress on a written project:
Ideally I would like the more recent dates to be shown more spread out on the x-axis, but still labelled correctly as dates. This would look a bit like a logarithmic scale in reverse. I think this idea might be quite useful for timelines in contexts where progress accelerates over time, e.g. computation power.
I’ve looked at this matplotlib "timeline" example for inspiration, but can’t quite see how to achieve the spacing and labelling I want.
Here is a minimal example to work with:
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from io import StringIO
data = '''when,words
2019-11-11,537
2019-12-19,530
2020-03-16,876
2020-08-10,1488
2021-02-05,2222
2022-01-21,2839
2022-03-02,3050
2022-03-04,3296
2022-03-15,3370
2022-03-23,3575
2022-04-25,2711
2022-06-06,3014
2022-06-28,3130
'''
prog = pd.read_csv(StringIO(data), parse_dates=['when'])
fig, ax = plt.subplots(figsize=(6,6))
sns.lineplot(ax=ax,data=prog,x="when",y="words",markers=True,marker="o")
ax.set(ylim=(0,1.1*prog.words.max()),title="Dissertation Progress")
fig.autofmt_xdate()
fig.tight_layout()
Answers:
You may try something along these lines, i.e. converting your dates to number of days and then applying np.log10()
on them:
prog.loc[:,'days'] = -np.log10(abs((prog.when - prog.iloc[-1].when).dt.days - 100))
g = sns.lineplot(x="days",y="words",data=prog,markers=True,marker="o")
_ = g.set_xticks(prog.days.to_list(), prog.when.dt.date.to_list(), rotation=90)
This yields this plot:
You can then handle overlapping labels by manually adjusting the xticklabels.
In a few recent applications I have plotted some time series where the more recent values are of more interest, but the historical values are good for context. Here’s an example, a toy tracker for progress on a written project:
Ideally I would like the more recent dates to be shown more spread out on the x-axis, but still labelled correctly as dates. This would look a bit like a logarithmic scale in reverse. I think this idea might be quite useful for timelines in contexts where progress accelerates over time, e.g. computation power.
I’ve looked at this matplotlib "timeline" example for inspiration, but can’t quite see how to achieve the spacing and labelling I want.
Here is a minimal example to work with:
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from io import StringIO
data = '''when,words
2019-11-11,537
2019-12-19,530
2020-03-16,876
2020-08-10,1488
2021-02-05,2222
2022-01-21,2839
2022-03-02,3050
2022-03-04,3296
2022-03-15,3370
2022-03-23,3575
2022-04-25,2711
2022-06-06,3014
2022-06-28,3130
'''
prog = pd.read_csv(StringIO(data), parse_dates=['when'])
fig, ax = plt.subplots(figsize=(6,6))
sns.lineplot(ax=ax,data=prog,x="when",y="words",markers=True,marker="o")
ax.set(ylim=(0,1.1*prog.words.max()),title="Dissertation Progress")
fig.autofmt_xdate()
fig.tight_layout()
You may try something along these lines, i.e. converting your dates to number of days and then applying np.log10()
on them:
prog.loc[:,'days'] = -np.log10(abs((prog.when - prog.iloc[-1].when).dt.days - 100))
g = sns.lineplot(x="days",y="words",data=prog,markers=True,marker="o")
_ = g.set_xticks(prog.days.to_list(), prog.when.dt.date.to_list(), rotation=90)
This yields this plot:
You can then handle overlapping labels by manually adjusting the xticklabels.