【问题标题】:100% stacked area/histogram in matplotlib with dates on X axismatplotlib 中 100% 的堆积面积/直方图,X 轴上带有日期
【发布时间】:2017-07-01 14:19:11
【问题描述】:

我想充分利用thisthis 的问题。也就是说,我有一个DataFrame,其中包含测试名称、执行日期和结果。我想展示失败案例的百分比如何随着时间的推移而下降。

我的数据如下所示:

TestName;Date;IsPassed
test1;12/8/2016 9:44:30 PM;0
test1;12/8/2016 9:39:00 PM;0
test1;12/8/2016 9:38:29 PM;1
test1;12/8/2016 9:38:27 PM;1
test2;12/8/2016 5:05:02 AM;1
test3;12/7/2016 8:58:36 PM;0
test3;12/7/2016 8:57:19 PM;1
test3;12/7/2016 8:56:15 PM;1
test4;12/5/2016 6:50:49 PM;0
test4;12/5/2016 6:49:50 PM;0
test4;12/5/2016 3:23:09 AM;1
test4;12/4/2016 11:51:29 PM;1

我正在使用此代码分别绘制案例:

fig, ax = plt.subplots()
passed = tests[tests.IsPassed == 1]
failed = tests[tests.IsPassed == 0]
passed_dates = mdates.date2num(passed.Date.astype(datetime))
failed_dates = mdates.date2num(failed.Date.astype(datetime))
ax.hist(passed_dates, bins=10, color='g')
ax.hist(failed_dates, bins=10, color='r')
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%y'))
plt.show()

但现在我想

  1. 将时间跨度划分为可配置数量的存储桶
  2. 计算每个存储桶的测试运行次数(没有 for 循环,因为数据框中有很多条目)
  3. 绘制 100% 面积图或每个桶的堆积直方图,以便步骤 2 的数量为 100%

我现在的问题是hist() 的完美工作解决方案会自动汇总,我看不到将 Y 轴传递给它的方法。

更新

这是我想要完成的(取自另一个来源):

【问题讨论】:

    标签: python matplotlib plot time histogram


    【解决方案1】:

    使用参数stacked = True 允许您提供多个数组作为plt.hist 的输入。

    ax.hist([passed_dates, failed_dates], bins=10, stacked=True, label=["passed", "failed"])
    

    使用相对计数需要除以每个 bin 的绝对计数。此功能未内置到 hist 函数中。您需要手动计算直方图,然后将结果绘制为堆积条形图。

    from __future__ import division
    import matplotlib.pyplot as plt
    import matplotlib.dates
    import datetime
    import numpy as np
    import pandas as pd
    
    dates = pd.date_range("2016/01/01","2016/06/01" )
    dates2 = pd.date_range("2016/02/01","2016/03/17", freq="18H")
    dates = dates.append(dates2)
    
    passed = np.round(np.random.rand(len(dates))+0.231).astype(np.int8)
    tests = pd.DataFrame({"Date" : dates, "IsPassed": passed})
    
    fig, ax = plt.subplots()
    passed = tests[tests.IsPassed == 1]
    failed = tests[tests.IsPassed == 0]
    all_dates = matplotlib.dates.date2num(tests.Date.astype(datetime.datetime))
    passed_dates = matplotlib.dates.date2num(passed.Date.astype(datetime.datetime))
    failed_dates = matplotlib.dates.date2num(failed.Date.astype(datetime.datetime))
    
    hist, bins = np.histogram(all_dates, bins=10)
    histpassed, bins_ = np.histogram(passed_dates, bins=bins)
    histfailed, bins__ = np.histogram(failed_dates, bins=bins)
    
    binwidth=bins[1]-bins[0]
    ax.bar(bins[:-1]+binwidth/2., histpassed/hist, width=binwidth*0.8, label="passed")
    ax.bar(bins[:-1]+binwidth/2., histfailed/hist, width=binwidth*0.8, bottom=histpassed/hist, label="failed")
    
    ax.xaxis.set_major_locator(matplotlib.dates.AutoDateLocator())
    ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%d.%m.%y'))
    ax.legend()
    fig.autofmt_xdate()
    plt.savefig(__file__+".png")
    plt.show()
    

    【讨论】:

    • 不错!感谢您的提示。现在有没有办法从 Y 轴上的绝对计数切换到百分比?现在有些垃圾箱总计超过一千次,而其他垃圾箱不到 100...
    • 查看编辑后的答案。如果这仍然没有帮助,请随时进一步询问。
    • 这正是我一直在寻找的!谢谢,@ImportanceOfBeingErnest!有几件事想改变以适应我的需求,但这些都不是这个问题的主题。