Python Seaborn tsplot 不能很好地在 x 轴上显示日期时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31255815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 09:42:16  来源:igfitidea点击:

Seaborn tsplot does not show datetimes on x axis well

pythondatetimematplotlibseaborn

提问by sedavidw

Below I have the following script which creates a simple time series plot:

下面我有以下脚本,它创建一个简单的时间序列图:

%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()

And the result of this is the following:

结果如下:

enter image description here

在此处输入图片说明

As you can see the x-axis has strange numbers for the datetimes, and not the usual "nice" representations that come with matplotliband other plotting utilities. I've tried many things, re-formatting the data but it never comes out clean. Anyone know a way around?

正如您所看到的,x 轴的日期时间有奇怪的数字,而不是matplotlib其他绘图实用程序附带的通常的“漂亮”表示。我尝试了很多东西,重新格式化数据,但它永远不会干净。有谁知道解决办法吗?

采纳答案by hitzg

Matplotlib represents dates as floating point numbers (in days), thus unless you (or pandas or seaborn), tell it that your values are representing dates, it will not format the ticks as dates. I'm not a seaborn expert, but it looks like it (or pandas) does convert the datetimeobjects to matplotlib dates, but then does not assign proper locators and formatters to the axes. This is why you get these strange numbers, which are in fact just the days since 0001.01.01. So you'll have to take care of the ticks manually (which, in most cases, is better anyways as it gives you more control).

Matplotlib 将日期表示为浮点数(以天为单位),因此除非您(或 pandas 或 seaborn)告诉它您的值表示日期,否则它不会将刻度格式化为日期。我不是seaborn专家,但看起来它(或pandas)确实将datetime对象转换为matplotlib日期,但没有为轴分配适当的定位器和格式化程序。这就是为什么你会得到这些奇怪的数字,这些数字实际上只是自 0001.01.01 以来的日子。因此,您必须手动处理滴答声(在大多数情况下,这更好,因为它可以为您提供更多控制权)。

So you'll have to assign a date locator, which decides where to put ticks, and a date formatter, which will then format the strings for the tick labels.

因此,您必须分配一个日期定位器,它决定在哪里放置刻度,以及一个日期格式化器,然后将格式化刻度标签的字符串。

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()

Result:

结果:

enter image description here

在此处输入图片说明

回答by T Smith

For me, @hitzg's answer results in "OverflowError: signed integer is greater than maximum" in the depths of DateFormatter.

对我来说,@hitzg 的回答导致 DateFormatter 深度中的“溢出错误:有符号整数大于最大值”。

Looking at my dataframe, my indices are datetime64, not datetime. Pandas converts these nicely though. The following works great for me:

查看我的数据框,我的索引是 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))

回答by ltjds

Here is a potentially inelegant solution, but it's the only one I have ... Hope it helps!

这是一个可能不优雅的解决方案,但它是我唯一的解决方案......希望它有所帮助!

    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');

Let me know if you see any issues!

如果您发现任何问题,请告诉我!

回答by peter254

def myFormatter(x, pos):
       return pd.to_datetime(x).strftime('%Y%m%d')
ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter))