简体   繁体   English

Matplotlib 图形 x 刻度是在所有 x 数据点之后

[英]Matplotlib graph x ticks are after all x data points

I am graphing timestamps against integers on a binary step graph, but it had all the timestamps on the x axis that are plotted instead of intervals, so I tried manually setting the x ticks to every 15 minutes throughout a day, but all the ticks seem to be after the data points:我在二进制步进图上针对整数绘制时间戳,但它在 x 轴上绘制了所有时间戳而不是间隔,所以我尝试手动将 x 刻度设置为全天每 15 分钟一次,但所有刻度似乎在数据点之后: 在此处输入图片说明

Without trying to manually set the ticks:无需尝试手动设置刻度: 在此处输入图片说明

The data that is being plotted is in the following format:正在绘制的数据采用以下格式:

[['21:20:24', '21:21:15', '51', '1'], ['21:27:55', '21:29:15', '80', '1'], ['21:38:16', '21:40:15', '119', '1'], ['22:13:44', '22:19:31', '347', '3'], ['22:24:42', '22:26:15', '93', '1'], ['22:47:29', '22:49:15', '106', '1']] (which is produced by self.padDs() function) [['21:20:24', '21:21:15', '51', '1'], ['21:27:55', '21:29:15', '80', '1'], ['21:38:16', '21:40:15', '119', '1'], ['22:13:44', '22:19:31', '347', '3'], ['22:24:42', '22:26:15', '93', '1'], ['22:47:29', '22:49:15', '106', '1']] (由 self.padDs() 函数产生)

What can I do to fix the ticks?我能做些什么来修复蜱虫?

#Plot as binary step graph
def binaryGraph(self, day):
    fig = plot.figure(figsize=(17, 2))
    ax = fig.add_subplot(111)

    allData = self.getAllFromDir("datastream/"+day+"/")
    i = 1
    for ds in allData:
        padded = self.padDs(ds)
        x = []
        y = []
        for line in padded:
            x.append(line[0])
            y.append(int(line[2]))
            x.append(line[1])
            y.append(int(line[2]))

        ax.step(x,y, label=day+str(i))
        i = i + 1
        break

    plot.title(day)
    plot.xlabel("Time")
    plot.ylabel("Interval length (s)")
    plot.legend()
    ticks = []
    for i in range(0, 25):
        tick = str(i)+":"
        if i < 10:
            tick = "0"+str(i)+":"

        for j in range(0, 60, 15):
            mins = tick + str(j)
            if j == 0:
                mins = tick + "0"+ str(j)
            ticks.append(mins)

    plot.xticks(ticks)
    print(ticks)
    plot.show()

Calling plt.xticks with just one parameter of strings isn't a good approach.仅使用一个字符串参数调用plt.xticks不是一种好方法。 The first parameter to xticks should be a list of numbers, places in the x-axis where you want a tick. xticks的第一个参数应该是一个数字列表,在 x 轴上你想要一个刻度的位置。 The optional second parameter would be the list of strings to be written at those ticks.可选的第二个参数是要在这些刻度上写入的字符串列表。

In your case, you have just strings for the x-axis.在您的情况下,您只有 x 轴的字符串。 Internally, they are just numbers 0,1,2,... .在内部,它们只是数字0,1,2,... This means that in the current plot, the width of all the steps is equal, being exactly one position.这意味着在当前图中,所有步骤的宽度相等,恰好是一个位置。

One way to go further, is to make the x-axis numerically, for example measuring in minutes.更进一步的一种方法是以数字方式制作 x 轴,例如以分钟为单位进行测量。 That way the width of your steps can be proportional to the interval length.这样,您的步骤的宽度可以与间隔长度成正比。

In that case, you can calculate ticks for every 15 minutes.在这种情况下,您可以每 15 分钟计算一次刻度。 And tick labels for each of these ticks as hours and minutes ( HH:MM ).并将每个刻度的刻度标签标记为小时和分钟 ( HH:MM )。

Here is some code to do just that.这里有一些代码可以做到这一点。 I chose a smaller font and rotated the labels to make them fit on the page.我选择了较小的字体并旋转了标签以使它们适合页面。

from matplotlib import pyplot as plt

fig = plt.figure(figsize=(17, 2))
ax = fig.add_subplot(111)

padded = [['21:20:24', '21:21:15', '51', '1'], ['21:27:55', '21:29:15', '80', '1'], ['21:38:16', '21:40:15', '119', '1'], ['22:13:44', '22:19:31', '347', '3'], ['22:24:42', '22:26:15', '93', '1'], ['22:47:29', '22:49:15', '106', '1']]
x = []
y = []
for line in padded:
    # change x's from text to a number in minutes
    x0, x1 = [int(h) * 60 + int(m) + int(s) / 60.0 for i in (0, 1) for h, m, s in [line[i].split(':')]]
    x.append(x0)
    y.append(int(line[2]))
    x.append(x1)
    y.append(int(line[2]))

ax.step(x, y, label="day_i")

plt.title("day")
plt.xlabel("Time")
plt.ylabel("Interval length (s)")
plt.legend()
ticks = []
labels = []
for i in range(0, 25):
    for j in range(0, 60, 15):
        labels.append(f"{i:02}:{j:02}")
        ticks.append(i * 60 + j)
        if i == 24:  # make 24:00 the last tick
            break
plt.xticks(ticks, labels, rotation=90, fontsize=8)
plt.tight_layout()
plt.show()

结果图

The code to generate the ticks could be made more Pythonic as follows.可以使生成刻度的代码更加 Pythonic,如下所示。

ticks = range(0, 24*60+1, 15)
labels = [f"{m // 60:02}:{m % 60:02}" for m in ticks]

The advantage is that you can just change the ticks and the labels will still be OK.优点是您只需更改刻度,标签仍然可以。 For example:例如:

ticks = range(0, 24*60+1, 60)
labels = [f"{m // 60:02}:{m % 60:02}" for m in ticks]
minor_ticks = range(0, 24*60+1, 15)
plt.xticks(ticks, labels, fontsize=10)
ax.xaxis.set_ticks(minor_ticks, minor=True)

Probably, while creating the y array, you could set the second y to 0 , as the step plot already takes care of drawing steps, and the 0 would be useful for the inbetween-intervals without data.可能在创建y数组时,您可以将第二个y设置为0 ,因为阶梯图已经处理了绘制步骤,并且 0 对于没有数据的中间间隔很有用。 In that case, you need to add where='post' to the step plot (to indicate that a new step is valid for after the x0).在这种情况下,您需要将where='post'添加到step图(以指示新步骤在 x0 之后有效)。 And you'd need to add an extra 0 at the start and end of the day ( ax.step([0]+x+[24*60], [0]+y+[0], where='post', label=...) ).并且您需要在一天的开始和结束时添加一个额外的 0( ax.step([0]+x+[24*60], [0]+y+[0], where='post', label=...) )。

Zooming in on your example data would look like:放大示例数据如下所示: 示例放大图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM