多索引DataFrame的分面图

时间:2017-04-18 00:35:00

标签: pandas seaborn

如何为每个频道(inapp,电子邮件,推送)绘制三个时间序列,其中色调变化为“已启用”'用大熊猫和海鸟?请注意,列是MultiIndexed。我希望这些图分享y轴并有一个共同的图例来表示'已启用'。

|---------|---------------|--------------|---------------|
| channel | inapp         | email        | push          |
| enabled | true  | false | false | true | false | true  |
|---------|-------|-------|-------|------|-------|-------|
| 0       | 0     | 80    | 28    | 0    | 5     | 0     |
| 1       | 2     | 80    | 28    | 3    | 5     | 233   |
| 2       | 4     | 80    | 28    | 7    | 5     | 587   |
| 3       | 5     | 80    | 28    | 12   | 5     | 882   |
| 4       | 7     | 86    | 28    | 16   | 5     | 1292  |
|---------|-------|-------|-------|------|-------|-------|

2 个答案:

答案 0 :(得分:1)

可能没有必要使用Seaborn 这是构建您指定的数据框的代码:

import pandas as pd

enabled = [True, False]
channel =['inapp','email','push']
values = [0,2,4,5,7,80,80,80,80,86,28,28,28,28,28,
          0,3,7,12,16,5,5,5,5,5,0,233,587,882,1292]
values = np.array(values).reshape((5,6), order='F')

columns = pd.MultiIndex.from_product([channel,enabled], 
                                     names=("channel","enabled"))
df = pd.DataFrame(values, columns=columns)

channel inapp       email        push      
enabled True  False True  False True  False
0           0    80    28     0     5     0
1           2    80    28     3     5   233
2           4    80    28     7     5   587
3           5    80    28    12     5   882
4           7    86    28    16     5  1292  

假设您引用的时间序列由索引值0-4组成,如果使用pyplot创建子图可以接受,则以下代码将符合您的规范:

from matplotlib import pyplot as plt  

fig, ax = plt.subplots(1, 3, sharey=True)
for i, col in enumerate(channel):
    df.T.xs(col).T.plot(ax=ax[i], xticks=df.index, title=col)

panel plot

当然,换位有点体操。使用groupby()可能会有Pandas-fu方式达到相同的效果,但是我玩了一下它并没有找到解决方案。希望这会有所帮助。

答案 1 :(得分:1)

这是另一种方式,使用Paul H的.stack()方法(尽管我也无法用FacetGrid来解决这个问题):

import pandas as pd
from matplotlib import pyplot as plt

enabled = [True, False]
channel =['inapp','email','push']
values = [0,2,4,5,7,80,80,80,80,86,28,28,28,28,28,
          0,3,7,12,16,5,5,5,5,5,0,233,587,882,1292]
values = np.array(values).reshape((5,6), order='F')

columns = pd.MultiIndex.from_product([channel,enabled], names=("channel","enabled"))
df = pd.DataFrame(values, columns=columns)

fig, ax = plt.subplots(1,3,sharey=True)

for i, (key, group) in enumerate(df.stack(level='channel').reset_index(level=1).groupby('channel')):
    group.plot(label=key, title=key, ax=ax[i])

<强>更新
这是一个更紧凑的版本,使用unstack()factorplot() rename行只是为了清晰,可以删除它。

df = (df.unstack('enabled')
        .reset_index()
        .rename(columns={'level_2':'time',0:'value'})
)
sns.factorplot(data=df, x='time', y='value', hue='enabled', col='channel')

timeseries plot