根据同一图表中matplotlib中不同时间戳的多个X值绘制多个Y值?

时间:2014-07-17 23:19:31

标签: python graph matplotlib

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

CSV1: 时间戳,data1

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: 时间戳,data2

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: 时间戳,data3

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值,每个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个小时以上的数据点。因此,当我绘制时,我得到一个非常糟糕的图表。我如何解决它 ?但是,当我有少量数据时,我会得到一个合适的图表。

2 个答案:

答案 0 :(得分:2)

好的,我更新了我的初步答案。这是一种可能的解决方案。但是既然你在谈论一个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()

enter image description here

答案 1 :(得分:0)

这是我如何处理这个问题。

首先,尝试利用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标签
plt.xticks(np.arange(number_seconds), time_stamps_fmt)