虽然宽度<1,但Python matplotlib条重叠。 1

时间:2017-09-12 11:59:43

标签: python matplotlib

我试图绘制一些带有matplotlib的条形图,其中x轴正好有26个时间戳/槽,y轴有两个整数。对于大多数数据集,这可以很好地扩展,但在某些情况下,matplotlib可以让条重叠:

Left overlapping and not aligned to xticks, right one OK

Overlapping

因此,虽然我的宽度设置为0.1而我的数据集有26个值,而不是为条形图提供足够的空间,所以我检查了它们。

我绘制这些图表的代码如下:

# Plot something
rows = len(data_dict) // 2 + 1
fig = plt.figure(figsize=(15, 5*rows))
gs1 = gridspec.GridSpec(rows, 2)
grid_x = 0
grid_y = 0

for dataset_name in data_dict:
    message1_list = []
    message2_list = []
    ts_list = []
    slot_list = []
    for slot, counts in data_dict[dataset_name].items():
        slot_list.append(slot)
        message1_list.append(counts["Message1"])
        message2_list.append(counts["Message2"])
        ts_list.append(counts["TS"])

    ax = fig.add_subplot(gs1[grid_y, grid_x])

    ax.set_title("Activity: " + dataset_name, fontsize=24)
    ax.set_xlabel("Timestamps", fontsize=14)
    ax.set_ylabel("Number of messages", fontsize=14)

    ax.xaxis_date()
    hfmt = matplotdates.DateFormatter('%d.%m,%H:%M')
    ax.xaxis.set_major_formatter(hfmt)

    ax.set_xticks(ts_list)
    plt.setp(ax.get_xticklabels(), rotation=60, ha='right')
    ax.tick_params(axis='x', pad=0.75, length=5.0)

    rects = ax.bar(ts_list, message2_list, align='center', width=0.1)
    rects2 = ax.bar(ts_list, message1_list, align='center', width=0.1, bottom=message2_list)

    # update grid position
    if (grid_x == 1):
        grid_x = 0
        grid_y += 1
    else:
        grid_x = 1


plt.tight_layout(0.01)
plt.savefig(r"output_files\activity_barcharts.svg",bbox_inches='tight')
plt.gcf().clear()

输入数据如下所示(带有重叠条的图表示例,第二张图片)

    slot - message1 - message2 - timestamp
    0 - 0 - 42 - 2017-09-11 07:59:53.517000+00:00
    1 - 0 - 4 - 2017-09-11 09:02:28.827875+00:00
    2 - 0 - 0 - 2017-09-11 10:05:04.138750+00:00
    3 - 0 - 0 - 2017-09-11 11:07:39.449625+00:00
    4 - 0 - 0 - 2017-09-11 12:10:14.760500+00:00
    5 - 0 - 0 - 2017-09-11 13:12:50.071375+00:00
    6 - 0 - 13 - 2017-09-11 14:15:25.382250+00:00
    7 - 0 - 0 - 2017-09-11 15:18:00.693125+00:00
    8 - 0 - 0 - 2017-09-11 16:20:36.004000+00:00
    9 - 0 - 0 - 2017-09-11 17:23:11.314875+00:00
    10 - 0 - 0 - 2017-09-11 18:25:46.625750+00:00
    11 - 0 - 0 - 2017-09-11 19:28:21.936625+00:00
    12 - 0 - 0 - 2017-09-11 20:30:57.247500+00:00
    13 - 0 - 0 - 2017-09-11 21:33:32.558375+00:00
    14 - 0 - 0 - 2017-09-11 22:36:07.869250+00:00
    15 - 0 - 0 - 2017-09-11 23:38:43.180125+00:00
    16 - 0 - 0 - 2017-09-12 00:41:18.491000+00:00
    17 - 0 - 0 - 2017-09-12 01:43:53.801875+00:00
    18 - 0 - 0 - 2017-09-12 02:46:29.112750+00:00
    19 - 0 - 0 - 2017-09-12 03:49:04.423625+00:00
    20 - 0 - 0 - 2017-09-12 04:51:39.734500+00:00
    21 - 0 - 0 - 2017-09-12 05:54:15.045375+00:00
    22 - 0 - 0 - 2017-09-12 06:56:50.356250+00:00
    23 - 0 - 0 - 2017-09-12 07:59:25.667125+00:00
    24 - 0 - 20 - 2017-09-12 09:02:00.978000+00:00
    25 - 0 - 0 - 2017-09-12 10:04:36.288875+00:00

有谁知道如何防止这种情况发生? 我为每张图表精确计算了26个条形图,实际上预计它们具有相同的宽度。我也尝试用1e-5替换0,但这并没有阻止任何重叠(另一篇文章提出)。

1 个答案:

答案 0 :(得分:0)

栏的 width 数据单位的宽度。即如果你想要一个宽度为1分钟的条形,你可以将width设置为

plt.bar(..., width=1./(24*60.))

因为matplotlib中日期时间轴的数字轴单位是天,一天有24 * 60分钟。

对于条形宽度的自动确定,您可能会说条形宽度是输入时间列表中任意两个连续值之间的最小差异。在这种情况下,类似下面的内容将起到作用

import numpy as np
import matplotlib.pyplot as plt
import datetime
import matplotlib.dates

t = [datetime.datetime(2017,9,12,8,i) for i in range(60)]
x = np.random.rand(60)

td = np.diff(t).min()
s1 = matplotlib.dates.date2num(datetime.datetime.now())
s2 = matplotlib.dates.date2num(datetime.datetime.now()+td)

plt.bar(t, x, width=s2-s1, ec="k")

plt.show()

enter image description here