【问题标题】:Plotting multiple Y values against multiple X values which are different timestamps in matplotlib in the same graph?在同一张图中,针对多个 X 值绘制多个 Y 值,这些 X 值是 matplotlib 中不同的时间戳?
【发布时间】:2014-09-09 00:08:05
【问题描述】:

我是matplotlib的新手,所以请原谅我的无知并帮助我解决这个问题。本质上,我有以下数据由 CSV 文件中的其他 python 脚本生成。

CSV1: 时间戳,数据1

23:04:17, 1163557.14 bps
23:04:27, 1137578.47 bps
23:04:37, 1139094.66 bps
23:04:47, 1095752.97 bps
23:04:57, 1264145.01 bps

CSV2: 时间戳,数据2

23:04:21, 1011000.00 bps
23:04:31, 1011000.00 bps
23:04:41, 1011000.00 bps
23:04:51, 1014000.00 bps
23:05:01, 1008000.00 bps

CSV3: 时间戳,数据3

23:05:28, 1109617.96 bps
23:05:38, 1139177.95 bps
23:05:48, 1108110.09 bps
23:05:58, 1107078.94 bps
23:06:08, 1163406.80 bps

我想要的是让时间沿 X 轴运行,并让沿 Y 轴的三个 Y 值分别显示“data1”、“data2”和“data3”。每 10 秒收集一次数据,但它们不一定是同步的。所以我不能有一个 X 轴数组。但我希望所有这些都在同一张图中进行比较。我怎么解决这个问题 ?

非常感谢任何示例代码或文档说明。

**编辑:

基本上我的问题是数据是按照不同的时间戳索引的,但我想将它们绘制在同一张图上。我该怎么做?**

编辑2:

感谢大家的意见。这真的很有帮助。所以这是我现在的代码:

    import csv
    import sys
    import datetime
    import random
    import matplotlib.pyplot as plt
    from matplotlib.dates import MinuteLocator, SecondLocator, DateFormatter

    time_e_z_raw_list = []
    bitrate_e_z_list = []
    time_i_z_raw_list = []
    bitrate_i_z_list = []
    time_i_query_z_raw_list = []
    bitrate_i_q_z_raw_list = []

    f_enc_z = open(sys.argv[1], 'rt')
    f_ing_z = open(sys.argv[2], 'rt')
    f_ing_q_z = open(sys.argv[3], 'rt')

    try:
        reader1 = csv.reader(f_enc_z)
        for row in reader1:
            bitrate = row[1]
            time_e_z_raw_list.append(row[0])
            bitrate_e_z_list.append(bitrate[:-4])
        reader3 = csv.reader(f_ing_z)
        for row in reader3:
            bitrate = row[1]
            time_i_z_raw_list.append(row[0])
            bitrate_i_z_list.append(bitrate[:-4])
        reader4 = csv.reader(f_ing_q_z)
        for row in reader4:
            bitrate = row[1]
            time_i_q_z_raw_list.append(row[0])
            bitrate_i_q_z_raw_list.append(bitrate[:-4])

    finally:
        f_enc_z.close()
        f_ing_z.close()
        f_ing_q_z.close()

    time_e_z_list = [datetime.datetime.strptime(s, '%H:%M:%S') for s in         time_e_z_raw_list]
    time_i_z_list = [datetime.datetime.strptime(s, '%H:%M:%S') for s in     time_i_z_raw_list]
    time_i_q_z_list = [datetime.datetime.strptime(s, '%H:%M:%S') for s in time_i_q_z_raw_list]

    fig = plt.figure(figsize=(18,16))

    plt.plot(time_e_z_list, bitrate_e_z_list, label="label1", lw=1)
    plt.plot(time_i_z_list, bitrate_i_z_list, label="label2", lw=1)
    plt.plot(time_i_q_z_list, bitrate_i_z_list, label="label3", lw=1)

    minutes = MinuteLocator()
    seconds = SecondLocator()

    ax = plt.gca()
    ax.xaxis.set_major_locator(minutes)
    ax.xaxis.set_minor_locator(seconds)
    ax.xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
    plt.xlabel('time')
    plt.ylabel('bitrate in bps')
    plt.grid()
    plt.legend(loc='upper right')

    plt.gcf().autofmt_xdate()

    plt.show()

问题是,当我的时间戳超过 3 小时时,图表会失真。如何确保 X 轴显示的范围根据我采样的时间戳范围动态调整?通常,我每 20 秒运行 4 个以上的数据点。所以当我绘图时,我得到一个非常糟糕的图表。我如何解决它 ?但是,当我有少量数据时,我会得到一个合适的图表。

【问题讨论】:

    标签: python graph matplotlib


    【解决方案1】:

    好的,我更新了最初的答案。这是一种可能的解决方案。但由于您谈论的是 CSV 文件,您可能想看看如何在 Pandas 中使用时间序列。

    import datetime
    import random
    import matplotlib.pyplot as plt
    
    data1 = (1163557.14, 1137578.47, 1139094.66)
    times1_raw = ('23:04:17', '23:04:27', '23:04:37')
    times1 = [datetime.datetime.strptime(s, '%H:%M:%S') for s in times1_raw]
    
    data2 = (1011000.00, 1011000.00, 1011000.00)
    times2_raw = ('23:04:21', '23:04:31', '23:04:41')
    times2 = [datetime.datetime.strptime(s, '%H:%M:%S') for s in times2_raw]
    
    fig = plt.figure(figsize=(8,6))
    
    plt.plot(times1, data1, label='data1', lw=2, marker='o')
    plt.plot(times2, data2, label='data2', lw=2, marker='s')
    plt.xlabel('time in seconds')
    plt.ylabel('speed in bps')
    plt.grid()
    plt.legend(loc='upper right')
    
    plt.gcf().autofmt_xdate()
    
    plt.show()
    

    【讨论】:

    • 理想情况下,我也希望时间戳保持完整。所以我希望时间戳沿着 X 轴运行。只是 data1 和 data2 的数据点偏离了几秒钟。 X轴上是否可以有时间戳?
    • 很高兴听到。也许你可以提供一些图片来展示这个问题的实际情况
    【解决方案2】:

    以下是我解决此问题的方法。

    首先,尝试利用datetime 模块。在处理带时间戳的数据时,它可以挽救生命。

    我们知道时间步长的最小增量是一秒。因此,让我们首先制作一个包含所有可能时间的列表。

    import matplotlib.pyplot as plt  
    import datetime
    
    start_date = datetime.datetime(2014,6,17,23,4,17)
    end_date = datetime.datetime(2014,6,17,23,6,8)
    number_seconds = (end_date - start_date).seconds
    
    time_stamps = [start_date + datetime.timedelta(seconds=t) for t in range(number_seconds)]
    

    现在列表time_stamps 是一个datetime 对象,我假设您只需要根据您的示例数据从邮票中获得小时:分钟:秒。我们可以通过更多的列表理解轻松地得到它:

    time_stamps_fmt = [datetime.datetime.strftime(t,'%H:%m:%S') for t in time_stamps]
    

    现在让我们创建一个空数组来存储 bps 数据:

    bps_1 = np.zeros([number_seconds],dtype('float'))
    bps_2 = np.zeros([number_seconds],dtype('float'))
    bps_3 = np.zeros([number_seconds],dtype('float'))
    

    然后将bps_1/2/3 的相应索引填充到 .csv 文件中的时间戳。如果未找到时间戳,则为该索引插入 np.nan,matplotlib 应将其视为缺失值而不绘制任何内容。

    您可以使用 xticks 将时间戳显示为 x-labels:

    plt.xticks(np.arange(number_seconds), time_stamps_fmt)
    

    【讨论】:

    • 这是您建议@N1B4 的一种有趣方式。但是如果我跑了超过 4 个小时,你认为每秒索引一次会有帮助吗?
    • 您必须至少以一秒的间隔存储数据,因为这是包含所有数据的最小频率。但是您是否需要绘制每个数据点?分钟平均值呢?还是 10 分钟的平均值?
    猜你喜欢
    • 2015-11-25
    • 1970-01-01
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    • 2021-10-16
    • 2019-03-08
    • 2019-06-10
    • 1970-01-01
    相关资源
    最近更新 更多