Seaborn tsplot 不能很好地在 x 轴上显示日期时间
Seaborn tsplot does not show datetimes on x axis well
下面是创建简单时间序列图的脚本:
%matplotlib inline
import datetime
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
df = []
start_date = datetime.datetime(2015, 7, 1)
for i in range(10):
for j in [1,2]:
unit = 'Ones' if j == 1 else 'Twos'
date = start_date + datetime.timedelta(days=i)
df.append({
'Date': date.strftime('%Y%m%d'),
'Value': i * j,
'Unit': unit
})
df = pd.DataFrame(df)
sns.tsplot(df, time='Date', value='Value', unit='Unit', ax=ax)
fig.autofmt_xdate()
结果如下:
如您所见,x 轴的日期时间数字很奇怪,而不是 matplotlib
和其他绘图实用程序附带的通常的“漂亮”表示。我已经尝试了很多东西,重新格式化数据,但它永远不会干净。有人知道解决办法吗?
Matplotlib 将日期表示为浮点数(以天为单位),因此除非您(或 pandas 或 seaborn)告诉它您的值表示日期,否则它不会将刻度格式化为日期。我不是 seaborn 专家,但看起来它(或 pandas)确实将 datetime
对象转换为 matplotlib 日期,但随后没有为轴分配适当的定位器和格式化程序。这就是为什么您会得到这些 奇怪数字 的原因,这些数字实际上就是自 0001.01.01 以来的日子。因此,您必须手动处理滴答声(在大多数情况下,这会更好,因为它可以让您更好地控制)。
所以你必须分配一个 date locator, which decides where to put ticks, and a date formatter,然后它将格式化刻度标签的字符串。
import datetime
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
# build up the data
df = []
start_date = datetime.datetime(2015, 7, 1)
for i in range(10):
for j in [1,2]:
unit = 'Ones' if j == 1 else 'Twos'
date = start_date + datetime.timedelta(days=i)
# I believe it makes more sense to directly convert the datetime to a
# "matplotlib"-date (float), instead of creating strings and then let
# pandas parse the string again
df.append({
'Date': mdates.date2num(date),
'Value': i * j,
'Unit': unit
})
df = pd.DataFrame(df)
# build the figure
fig, ax = plt.subplots()
sns.tsplot(df, time='Date', value='Value', unit='Unit', ax=ax)
# assign locator and formatter for the xaxis ticks.
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y.%m.%d'))
# put the labels at 45deg since they tend to be too long
fig.autofmt_xdate()
plt.show()
结果:
对我来说,@hitzg 的回答导致 "OverflowError: signed integer is greater than maximum" 在 DateFormatter 的深处。
查看我的数据框,我的索引是 datetime64,而不是 datetime。 Pandas 很好地转换了这些。以下对我很有用:
import matplotlib as mpl
def myFormatter(x, pos):
return pd.to_datetime(x)
[ . . . ]
ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter))
这是一个可能不太优雅的解决方案,但这是我唯一的解决方案......希望它能有所帮助!
g = sns.pointplot(x, y, data=df, ci=False);
unique_dates = sorted(list(df['Date'].drop_duplicates()))
date_ticks = range(0, len(unique_dates), 5)
g.set_xticks(date_ticks);
g.set_xticklabels([unique_dates[i].strftime('%d %b') for i in date_ticks], rotation='vertical');
g.set_xlabel('Date');
如果您发现任何问题,请告诉我!
def myFormatter(x, pos):
return pd.to_datetime(x).strftime('%Y%m%d')
ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter))
下面是创建简单时间序列图的脚本:
%matplotlib inline
import datetime
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
df = []
start_date = datetime.datetime(2015, 7, 1)
for i in range(10):
for j in [1,2]:
unit = 'Ones' if j == 1 else 'Twos'
date = start_date + datetime.timedelta(days=i)
df.append({
'Date': date.strftime('%Y%m%d'),
'Value': i * j,
'Unit': unit
})
df = pd.DataFrame(df)
sns.tsplot(df, time='Date', value='Value', unit='Unit', ax=ax)
fig.autofmt_xdate()
结果如下:
如您所见,x 轴的日期时间数字很奇怪,而不是 matplotlib
和其他绘图实用程序附带的通常的“漂亮”表示。我已经尝试了很多东西,重新格式化数据,但它永远不会干净。有人知道解决办法吗?
Matplotlib 将日期表示为浮点数(以天为单位),因此除非您(或 pandas 或 seaborn)告诉它您的值表示日期,否则它不会将刻度格式化为日期。我不是 seaborn 专家,但看起来它(或 pandas)确实将 datetime
对象转换为 matplotlib 日期,但随后没有为轴分配适当的定位器和格式化程序。这就是为什么您会得到这些 奇怪数字 的原因,这些数字实际上就是自 0001.01.01 以来的日子。因此,您必须手动处理滴答声(在大多数情况下,这会更好,因为它可以让您更好地控制)。
所以你必须分配一个 date locator, which decides where to put ticks, and a date formatter,然后它将格式化刻度标签的字符串。
import datetime
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
# build up the data
df = []
start_date = datetime.datetime(2015, 7, 1)
for i in range(10):
for j in [1,2]:
unit = 'Ones' if j == 1 else 'Twos'
date = start_date + datetime.timedelta(days=i)
# I believe it makes more sense to directly convert the datetime to a
# "matplotlib"-date (float), instead of creating strings and then let
# pandas parse the string again
df.append({
'Date': mdates.date2num(date),
'Value': i * j,
'Unit': unit
})
df = pd.DataFrame(df)
# build the figure
fig, ax = plt.subplots()
sns.tsplot(df, time='Date', value='Value', unit='Unit', ax=ax)
# assign locator and formatter for the xaxis ticks.
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y.%m.%d'))
# put the labels at 45deg since they tend to be too long
fig.autofmt_xdate()
plt.show()
结果:
对我来说,@hitzg 的回答导致 "OverflowError: signed integer is greater than maximum" 在 DateFormatter 的深处。
查看我的数据框,我的索引是 datetime64,而不是 datetime。 Pandas 很好地转换了这些。以下对我很有用:
import matplotlib as mpl
def myFormatter(x, pos):
return pd.to_datetime(x)
[ . . . ]
ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter))
这是一个可能不太优雅的解决方案,但这是我唯一的解决方案......希望它能有所帮助!
g = sns.pointplot(x, y, data=df, ci=False);
unique_dates = sorted(list(df['Date'].drop_duplicates()))
date_ticks = range(0, len(unique_dates), 5)
g.set_xticks(date_ticks);
g.set_xticklabels([unique_dates[i].strftime('%d %b') for i in date_ticks], rotation='vertical');
g.set_xlabel('Date');
如果您发现任何问题,请告诉我!
def myFormatter(x, pos):
return pd.to_datetime(x).strftime('%Y%m%d')
ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter))