如何按组绘制时间序列DataFrame,并根据条件更改行类型?

时间:2018-01-11 00:34:10

标签: python-2.7 pandas matplotlib pandas-groupby

我想知道如何在同一轴上的DataFrame中绘制时间序列,每个组使用不同的行。我还想根据某些(布尔)条件更改线型。这是一个例子:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from dateutil.parser import parse
from matplotlib import pyplot as plt

df = pd.DataFrame({'value': np.random.rand(18), 
              'group': ['A']*9 + ['B']*9,
              'future': [0, 0, 0, 0, 0, 0, 1, 1, 1]*2}, 
         index=[parse('2018-1-5') + timedelta(days=i) for i in range(9)]*2)

生成的DataFrame:

            future group     value
2018-01-05       0     A  0.076445
2018-01-06       0     A  0.800821
2018-01-07       0     A  0.410351
2018-01-08       0     A  0.039647
2018-01-09       0     A  0.664102
2018-01-10       0     A  0.192097
2018-01-11       1     A  0.456182
2018-01-12       1     A  0.163256
2018-01-13       1     A  0.832768
2018-01-05       0     B  0.139014
2018-01-06       0     B  0.265024
2018-01-07       0     B  0.832062
2018-01-08       0     B  0.738957
2018-01-09       0     B  0.334888
2018-01-10       0     B  0.945192
2018-01-11       1     B  0.707845
2018-01-12       1     B  0.135183
2018-01-13       1     B  0.140647

分组绘图很容易:

df.groupby('group')['value'].plot(legend='True')
plt.show()

enter image description here

但是,当future的对应值为1时,我希望这些线变为虚线。

以下是我尝试解决方案:

present_data = df.loc[df['future'] == 0]
future_data = df.loc[df['future'] == 1]

present_data.groupby('group')['value'].plot(legend='True')
future_data.groupby('group')['value'].plot(style='--')
plt.show()

enter image description here

但这不好。我想它可以通过手动设置颜色来修复(认为仍然留下线条中的间隙问题),但是肯定有比将数据框架分成两部分更好的方法吗?

非常感谢!

编辑:Will的解决方案对我来说很有用,但是我仍然想知道如何正确地创建传奇。我想为组'A'和'B'显示两条实线。

我试过了:

legends = []
for idx,grp in df_plot.groupby(['group','future']):
    grp['value'].plot(style=s[grp['future'][0]],color=c[grp['group'][0]])
    if grp['future'][0] == 0:
        legends.append(grp['group'][0])
    else:
        legends.append('')
plt.legend(legends)

但是这会导致虚线没有添加标签:

enter image description here

None附加到图例列表也不起作用。如果我完全跳过追加,'A'和'B'不对应正确的行:

legends = []
for idx,grp in df_plot.groupby(['group','future']):
    grp['value'].plot(style=s[grp['future'][0]],color=c[grp['group'][0]])
    if grp['future'][0] == 0:
        legends.append(grp['group'][0])
plt.legend(legends)
plt.show()

enter image description here

1 个答案:

答案 0 :(得分:3)

通过将分组合并为一个步骤,然后绘制每个组,您可以更轻松地手动指定颜色和样式。 为了消除差距,我认为你需要绘制一个额外的数据点。

extra=df[df.future==1]
extra = extra[extra.index == min(extra.index)] 
extra['future'] = 0
df_plot = pd.concat([df,extra])


s=['','--']
c={'A': 'red', 'B': 'blue'};

for idx,grp in df_plot.groupby(['group','future']):
    grp['value'].plot(style=s[grp['future'][0]],color=c[grp['group'][0]])

no gap plot