【问题标题】:A clear way to create a combination chart for time series data in matplotlib在 matplotlib 中为时间序列数据创建组合图表的清晰方法
【发布时间】:2021-07-18 15:54:34
【问题描述】:

我是matplotlib 的新用户。我已经学习了在 matplotlib 中绘制数据的基础知识。但我仍然无法理解如何绘制多个时间序列数据,如下所示:

情节包含一个传奇对我来说也很重要。

数据举例:

import pandas as pd
from io import StringIO
from matplotlib import pyplot as plt

data_str = '''time        x1   x2  x3  x4   
01.01.1984  100 -50  50  54 
01.02.1984  200 -20  180 7 
01.03.1984  250 -100 150 442413
01.04.1984  300 -50  250 7 
01.05.1984  250 -150 100 403 
01.06.1984  300 -200 100 148 
01.07.1984  200 -100 100 1096'''

df = pd.read_csv(StringIO(data_str), delim_whitespace=True)
df['time'] = pd.to_datetime(df['time'], format='%d.%m.%Y')
df = df.set_index('time')

ax = df['x3'].plot(grid=True, figsize=(10, 6), color='tab:grey', linewidth=4)

ax.bar(height=df['x1'], x=df.index, color='tab:blue', width=0.3, zorder=2, label='x1')
ax.bar(height=df['x2'], x=df.index, color='tab:orange', width=0.3, zorder=2, label='x2')

ax2 = ax.twinx()
ax2.set_yscale('log')
ax2.invert_yaxis()
df['x4'].plot.line(ax=ax2, color='gold', label='x4 (right)', linewidth=4)

ax.axhline(linewidth=1, color='black')
ax.set_xlabel('time', fontsize=16)
plt.xticks(size = 16)
plt.yticks(size = 16)

handles1, labels1 = ax.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
handles = handles1[1:] + handles1[:1] + handles2 # handles1 is reordered because it uses the line before the bars
labels = labels1[1:] + labels1[:1] + labels2

#order = [0,1,2,3]

ax.legend([handles[idx] for idx in order],[labels[idx] for idx in order],
          loc='upper center', bbox_to_anchor=(0.5, -0.2),
          fancybox=True, shadow=True, ncol=5,
          prop={'size': 16})



#plt.xlim(['1983-12-01', '1984-08-01'])
plt.show()

【问题讨论】:

    标签: python python-3.x matplotlib time-series data-visualization


    【解决方案1】:

    解释每一步超出了stackoverflow答案的范围。 online tutorials 是一个很好的起点。此外,建议的情节对于初学者的情节来说相当复杂。

    使用的一些函数示例:

    • pd.read_csv(filename, ...) 从 csv 文件中读取数据
    • StringIO(data_str) 是一种通过读取字符串来模拟文件的方法
    • plt.subplots 创建一个图形 (fig) 和子图 (称为 ax) 以进行绘图
    • df['x1'].plot.bar(...) 是一种用 pandas 绘制条形图的方法
    • df['x3'].plot.line(...) 是一种用 pandas 绘制线图的方法
    • ax1.twinx() 在右侧创建 y 轴
    • ...
    import pandas as pd
    from io import StringIO
    from matplotlib import pyplot as plt
    
    data_str = '''time        x1   x2  x3  x4   
    01.01.1984  100 -50  50  54 
    01.02.1984  200 -20  180 7 
    01.03.1984  250 -100 150 442413
    01.04.1984  300 -50  250 7 
    01.05.1984  250 -150 100 403 
    01.06.1984  300 -200 100 148 
    01.07.1984  200 -100 100 1096'''
    
    df = pd.read_csv(StringIO(data_str), delim_whitespace=True)
    fig, ax1 = plt.subplots(figsize=(10, 4))
    ax1.axhline(0, color='black', lw=2) # draw a long horizontal line at y=0
    df = df.set_index('time')
    df['x1'].plot.bar(ax=ax1, color='skyblue', label='x1')
    df['x2'].plot.bar(ax=ax1, color='darkorange', label='x2')
    df['x3'].plot.line(ax=ax1, color='slategray', label='x3')
    ax2 = ax1.twinx()
    ax2.set_yscale('log')
    df['x4'].plot.line(ax=ax2, color='gold', label='x4 (right)')
    
    handles1, labels1 = ax1.get_legend_handles_labels()
    handles2, labels2 = ax2.get_legend_handles_labels()
    handles = handles1[1:] + handles1[:1] + handles2 # handles1 is reordered because it uses the line before the bars
    labels = labels1[1:] + labels1[:1] + labels2
    ax1.legend(handles, labels, loc='upper center', bbox_to_anchor=(0.5, -0.1), ncol=len(handles))
    ax1.set_xlabel('')
    plt.tight_layout()
    plt.show()
    

    【讨论】:

    • 当我尝试向your graph 添加网格时,由于某种原因,网格不会相对于 y 轴(仅 x)显示。此外,网格叠加在图表本身上,而不是显示在其后面。看来这种情况下excell的可视化能力比matplotlib好)
    • 此外,如果数据框的索引是日期格式(df['time'] = pd.to_datetime(df['time'])),您的代码将无法正常工作
    • 好吧,您需要选择是让网格与左侧或右侧 y 轴一起移动,因为它们在同一位置没有刻度。请不要仅将软件与一个优化示例进行比较,该示例恰好与一个试图模仿另一个的默认值很好地工作。如果您想要日期的特定格式,可以将它们转换回字符串。
    • 感谢您的回答。事实证明它对我来说非常有价值。我几乎在matplotlib 中复制了相同的图表。但都一样,在excel 中,图表看起来更整洁一些。我不知道我还能如何改进我的图表以使其看起来更好。
    • 一个问题是,pandas 在将绘图与日期结合时会变得很困惑。如果可能,请将日期转换为您要使用的确切文本格式。请注意,pandas 条形图始终是分类的(等距条形图),而线形图则尽量是数字的(x 值是字符串时除外)。
    【解决方案2】:

    使用第二个 y 轴在一个图中(来自 Pandas 数据框,df)绘制多个系列的简单方法如下:

    df = pd.DataFrame({'time':[1,2,3,4,5,6,7], 
                       'x1':[100, 200, 250, 300, 250, 300, 200],
                       'x2':[-50,-20,-100,-50, -150, -200, -100],
                       'x3':[50, 180, 150, 250, 100, 100, 100],
                       'x4':[54, 7, 442413, 7, 403, 148, 1096]})
    
    plt.figure()
    df.x1.plot.bar()
    df.x2.plot.bar(color='red')
    df.x3.plot.line(color='red')
    df.x4.plot.line(color='green', secondary_y=True)
    

    【讨论】:

      猜你喜欢
      • 2019-01-04
      • 1970-01-01
      • 1970-01-01
      • 2020-05-27
      • 2014-05-03
      • 2020-12-24
      • 2017-06-24
      • 2021-06-23
      • 2020-03-17
      相关资源
      最近更新 更多