web-dev-qa-db-ja.com

Seaborn tsplotはx軸に日時をうまく表示しません

以下に、簡単な時系列プロットを作成する次のスクリプトがあります。

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

そして、この結果は次のとおりです。

enter image description here

ご覧のように、x軸には日時の奇妙な数値があり、matplotlibおよびその他のプロットユーティリティに付属している通常の "Nice"表現ではありません。私は多くのことを試して、データを再フォーマットしましたが、それがクリーンになることは決してありません。誰かが方法を知っていますか?

13
sedavidw

Matplotlibは日付を浮動小数点数(日数)で表します。したがって、(またはpandasまたはseaborn)でない限り、値が日付を表していると伝えない限り、ティックは日付としてフォーマットされません。シーボーンエキスパートではありませんが、それは(またはパンダ)がdatetimeオブジェクトをmatplotlib日付に変換するようですが、適切なロケーターとフォーマッターを軸に割り当てません。これが、これらを取得する理由です奇数、実際には0001.01.01以降の日数です。したがって、ティックを手動で処理する必要があります(ほとんどの場合、 、それはあなたにもっとコントロールを与えるのでとにかく良いです)。

したがって、目盛りを配置する場所を決定する date locator と、目盛りラベルの文字列をフォーマットする 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()

結果:

enter image description here

14
hitzg

私にとって、@ hitzgの答えは、DateFormatterの深さで「OverflowError:符号付き整数が最大値より大きい」という結果になります。

私のデータフレームを見ると、私のインデックスはdatetimeではなくdatetime64です。 Pandasでもこれらをうまく変換します。以下は私にとってとてもうまくいきます:

import matplotlib as mpl

def myFormatter(x, pos):
    return pd.to_datetime(x)

[ . . . ]

ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(myFormatter))
12
T Smith

これは潜在的に洗練されていない解決策ですが、私が持っている唯一の解決策です...それが役に立てば幸いです!

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

問題が発生した場合はお知らせください。

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