在 sns.lmplot() 中格式化 x 轴(日期)
format x-axis (dates) in sns.lmplot()
我有每日数据需要用 sns.lmplot()
绘制。
数据具有以下结构:
df = pd.DataFrame(columns=['date', 'origin', 'group', 'value'],
data = [['2001-01-01', "Peter", "A", 1.0],
['2011-01-01', "Peter", "A", 1.1],
['2011-01-02', "Peter", "B", 1.2],
['2012-01-03', "Peter", "A", 1.3],
['2012-01-01', "Peter", "B", 1.4],
['2013-01-02', "Peter", "A", 1.5],
['2013-01-03', "Peter", "B", 1.6],
['2021-01-01', "Peter", "A", 1.7]])
我现在想用 sns.lmplot()
绘制数据以获得月平均值(我的原始数据比玩具数据更细粒度)并使用 hue
来绘制 group
-柱子。为此,我按月汇总:
df['date'] = pd.to_datetime(df['date']).dt.strftime('%Y%M').astype(int)
df = df.groupby(['date', 'origin', 'group']).agg(['mean'])
df.columns = ["_".join(pair) for pair in df.columns] # reset col multi-index
df = df.reset_index() # reset index
然后我绘制数据:
sns.lmplot(data=df, x="date", y="value", hue="group",
ci=None, truncate=False, scatter_kws={"s": 1}, lowess=True, height=6, aspect=1.25)
plt.title(f"Title.")
plt.ylabel("Value")
plt.show()
这很好用,但日期很乱。我希望它们显示为日期而不是 int
s.
我找到了 question but I want the grouped plot, so I cannot use regplot, and the code plt.xticks(fake_dates)
(following 答案) 给出了 TypeError: object of type 'FuncFormatter' has no len()
.
有人知道如何解决这个问题吗?
- 为了将 x 轴上的值转换回日期,
'date'
列中的值应转换为序数值。
- 当遍历轴以配置
xtick
格式时,可以将标签配置为带有 .strftime
的自定义字符串格式
new_labels = [date.fromordinal(int(label)).strftime("%b %Y") for label in labels]
- 测试于
python 3.8.12
、pandas 1.3.3
、matplotlib 3.4.3
、seaborn 0.11.2
from datetime import date
# convert the date column to ordinal or create a new column
df['date'] = pd.to_datetime(df['date']).apply(lambda date: date.toordinal())
df = df.groupby(['date', 'origin', 'group']).agg(['mean'])
df.columns = ["_".join(pair) for pair in df.columns] # reset col multi-index
df = df.reset_index() # reset index
# plot
g = sns.lmplot(data=df, x="date", y="value_mean", hue="group", ci=None, truncate=False, scatter_kws={"s": 1}, lowess=True, height=6, aspect=1.5)
# iterate through the axes of the figure-level plot
for ax in g.axes.flat:
labels = ax.get_xticks() # get x labels
new_labels = [date.fromordinal(int(label)) for label in labels] # convert ordinal back to datetime
ax.set_xticks(labels)
ax.set_xticklabels(new_labels, rotation=0) # set new labels
plt.title("Title")
plt.ylabel("Value")
plt.show()
我有每日数据需要用 sns.lmplot()
绘制。
数据具有以下结构:
df = pd.DataFrame(columns=['date', 'origin', 'group', 'value'],
data = [['2001-01-01', "Peter", "A", 1.0],
['2011-01-01', "Peter", "A", 1.1],
['2011-01-02', "Peter", "B", 1.2],
['2012-01-03', "Peter", "A", 1.3],
['2012-01-01', "Peter", "B", 1.4],
['2013-01-02', "Peter", "A", 1.5],
['2013-01-03', "Peter", "B", 1.6],
['2021-01-01', "Peter", "A", 1.7]])
我现在想用 sns.lmplot()
绘制数据以获得月平均值(我的原始数据比玩具数据更细粒度)并使用 hue
来绘制 group
-柱子。为此,我按月汇总:
df['date'] = pd.to_datetime(df['date']).dt.strftime('%Y%M').astype(int)
df = df.groupby(['date', 'origin', 'group']).agg(['mean'])
df.columns = ["_".join(pair) for pair in df.columns] # reset col multi-index
df = df.reset_index() # reset index
然后我绘制数据:
sns.lmplot(data=df, x="date", y="value", hue="group",
ci=None, truncate=False, scatter_kws={"s": 1}, lowess=True, height=6, aspect=1.25)
plt.title(f"Title.")
plt.ylabel("Value")
plt.show()
这很好用,但日期很乱。我希望它们显示为日期而不是 int
s.
我找到了 plt.xticks(fake_dates)
(following TypeError: object of type 'FuncFormatter' has no len()
.
有人知道如何解决这个问题吗?
- 为了将 x 轴上的值转换回日期,
'date'
列中的值应转换为序数值。 - 当遍历轴以配置
xtick
格式时,可以将标签配置为带有.strftime
的自定义字符串格式new_labels = [date.fromordinal(int(label)).strftime("%b %Y") for label in labels]
- 测试于
python 3.8.12
、pandas 1.3.3
、matplotlib 3.4.3
、seaborn 0.11.2
from datetime import date
# convert the date column to ordinal or create a new column
df['date'] = pd.to_datetime(df['date']).apply(lambda date: date.toordinal())
df = df.groupby(['date', 'origin', 'group']).agg(['mean'])
df.columns = ["_".join(pair) for pair in df.columns] # reset col multi-index
df = df.reset_index() # reset index
# plot
g = sns.lmplot(data=df, x="date", y="value_mean", hue="group", ci=None, truncate=False, scatter_kws={"s": 1}, lowess=True, height=6, aspect=1.5)
# iterate through the axes of the figure-level plot
for ax in g.axes.flat:
labels = ax.get_xticks() # get x labels
new_labels = [date.fromordinal(int(label)) for label in labels] # convert ordinal back to datetime
ax.set_xticks(labels)
ax.set_xticklabels(new_labels, rotation=0) # set new labels
plt.title("Title")
plt.ylabel("Value")
plt.show()