如何使用多索引数据框创建 seaborn 回归图?

How can I create a seaborn regression plot with multiindex dataframe?

我有时间序列数据,在(年、月)上有多个索引,如下所示:

print(df.index)
print(df)
MultiIndex(levels=[[2016, 2017], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]],
           labels=[[0, 0, 0, 0, 0, 0, 0, 0], [2, 3, 4, 5, 6, 7, 8, 9]],
           names=['Year', 'Month'])
            Value
Year Month            
2016 3       65.018150
     4       63.130035
     5       71.071254
     6       72.127967
     7       67.357795
     8       66.639228
     9       64.815232
     10      68.387698

我想对这些时间序列数据进行非常基本的线性回归。因为pandas.DataFrame.plot不做任何回归,我打算用Seaborn做我的绘图。

我试图通过使用 lmplot:

来做到这一点
sns.lmplot(x=("Year", "Month"), y="Value", data=df, fit_reg=True) 

但是我得到一个错误:

TypeError: '>' not supported between instances of 'str' and 'tuple'

这对我来说特别有趣,因为 df.index.levels[:] 中的所有元素都是 numpy.int64 类型,df.index.labels[:] 中的所有元素都是 numpy.int8.[=20= 类型]

为什么我会收到此错误消息?我该如何解决?

考虑以下方法:

df['x'] = df.index.get_level_values(0) + df.index.get_level_values(1)/100

产量:

In [49]: df
Out[49]:
                Value        x
Year Month
2016 3      65.018150  2016.03
     4      63.130035  2016.04
     5      71.071254  2016.05
     6      72.127967  2016.06
     7      67.357795  2016.07
     8      66.639228  2016.08
     9      64.815232  2016.09
     10     68.387698  2016.10

让我们准备 X-ticks 标签:

labels = df.index.get_level_values(0).astype(str) + '-' + \
         df.index.get_level_values(1).astype(str).str.zfill(2)

sns.lmplot(x='x', y='Value', data=df, fit_reg=True)
ax = plt.gca()
ax.set_xticklabels(labels)

结果:

您可以使用 reset_index 将数据框的索引转换为列。然后使用 seaborn 直接绘制 DataFrames 列。

我猜想使用 lmplot 的原因是为了显示不同年份的不同回归(否则 regplot 可能更适合),可以使用 "Year" 列作为 hue.

import numpy as np
import pandas as pd
import seaborn.apionly as sns
import matplotlib.pyplot as plt

iterables = [[2016, 2017], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
index = pd.MultiIndex.from_product(iterables, names=['Year', 'Month'])
df = pd.DataFrame({"values":np.random.rand(24)}, index=index)

df2 = df.reset_index()  # or, df.reset_index(inplace=True) if df is not required otherwise 

g = sns.lmplot(x="Month", y="values", data=df2, hue="Year")

plt.show()