多索引 DataFrame 的多面图
Faceted plots of a multi-indexed DataFrame
如何使用 pandas 和 seaborn 绘制每个渠道(inapp、电子邮件、推送)的三个时间序列,色调变化 'enabled'?请注意,这些列是多索引的。我希望这些图共享 y 轴并有一个共同的图例来指示 'enabled'.
的值
|---------|---------------|--------------|---------------|
| 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 |
|---------|-------|-------|-------|------|-------|-------|
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)
诚然,换位有点费力。可能有 Pandas-fu 方法可以达到相同的效果,使用 groupby()
,但我试了一下,找不到解决方案。希望这有帮助。
这是另一种方法,使用 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')
如何使用 pandas 和 seaborn 绘制每个渠道(inapp、电子邮件、推送)的三个时间序列,色调变化 'enabled'?请注意,这些列是多索引的。我希望这些图共享 y 轴并有一个共同的图例来指示 'enabled'.
的值|---------|---------------|--------------|---------------| | 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 | |---------|-------|-------|-------|------|-------|-------|
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)
诚然,换位有点费力。可能有 Pandas-fu 方法可以达到相同的效果,使用 groupby()
,但我试了一下,找不到解决方案。希望这有帮助。
这是另一种方法,使用 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')