繁体   English   中英

不连续单杠 plot

[英]Discontinuous horizontal bar plot

考虑以下数据框

                 A      B
2022-09-28     1.3    0.0
2022-09-29     1.3    0.0
2022-09-30     1.3    0.9
2022-10-01     1.3    0.9
2022-10-02     0.0    0.9
2022-10-03     0.0    0.9
2022-10-04     0.0    0.0
2022-10-05     0.1    0.0
2022-10-06     0.1    0.0
2022-10-07     0.1    0.0

我需要一个水平条 plot,它具有两个垂直水平(A 和 B)和 x 轴上的日期。 条形的长度(条宽)等于非零值的时间间隔,线宽(条形高度)等于值的平均值。

例如,我们将在 A 级别设置两个栏。 第一个从 2022-09-28 到 2022-10-01,线宽 1.3,第二个从 2022-10-05 到 2022-10-07,线宽 0.1。 在 B 级别上,只有从 2022-09-30 到 2022-10-03 的一根柱线,线宽为 0.9。

非常接近,但它是每个级别仅一个条的解决方案。

您可以使用 Matplotlib 的broken_barh function 到 plot 各种不连续(“破碎”)水平条形图。 诀窍是将 dataframe 中的数据正确地提供给broken_barh :您需要为不连续柱 plot 的每个部分创建(x start, x duration)

例如,A 有您提到的两个部分。 一部分是(2022-09-28, 3 days) ,线宽为 1.3,第二部分是(2022-10-05, 2 days) ,线宽为 0.1。 我们将为broken_barh提供 x 范围[(2022-09-28, 3 days), (2022-10-05, 2 days)]和线宽[1.3, 0.1]

import matplotlib.pyplot as plt
import pandas as pd


if __name__ == '__main__':

    # Create dataframe    
    df_dates = pd.date_range('2022-09-28', periods=10)
    df = pd.DataFrame({'A': [1.3, 1.3, 1.3, 1.3, 0.0, 0.0, 0.0, 0.1, 0.1, 0.1],
                       'B': [0.0, 0.0, 0.9, 0.9, 0.9, 0.9, 0.0, 0.0, 0.0, 0.0]},
                      index=df_dates)

    # xranges and linewidth we will feed matplotlib later
    a_xranges = []
    a_lw = []

    # Find unique values in A - aka the parts of the A broken bar plot
    for lw_value in df['A'].unique().tolist():
        if lw_value != 0.0:  # skip 0.0, we will not plot it
            
            # Find rows where linewidth for the A values is located
            idx = df.index[df['A'] == lw_value].tolist()
            sub_df = df.loc[idx]

            # Find where the bar plot starts for x axis and x duration
            x_range = (sub_df.index[0], sub_df.index[-1] - sub_df.index[0])  # (x start, x duration)

            # Add x range and linewidth values for that part
            a_xranges.append(x_range)
            a_lw.append(lw_value)

a_xrangesa_lwbroken_barh的正确格式。 Matplotlib 将管理 pandas 日期,因此您不必担心日期格式。

您可以对 B 重复相同的操作 - 您也可以制作一个 function 并调用它,而不是添加相同的循环来清理您的代码。

    b_xranges = []
    b_lw = []

    for lw_value in df['B'].unique().tolist():
        if lw_value != 0.0:
            idx = df.index[df['B'] == lw_value].tolist()
            sub_df = df.loc[idx]
            x_range = (sub_df.index[0], sub_df.index[-1] - sub_df.index[0])   
            b_xranges.append(x_range)
            b_lw.append(lw_value)

    # Start figure
    fig, ax = plt.subplots(figsize=(12, 5))
    # Plot A bar plot
    # The (10,9) is for the y axis (ymin, y duration)
    ax.broken_barh(a_xranges, (10, 9), edgecolor='k', facecolor='white', linewidth=a_lw)
    # Plot B bar plot
    ax.broken_barh(b_xranges, (20, 9), edgecolor='k', facecolor='white', linewidth=b_lw)

    ax.set_ylabel("Level")
    ax.set_yticks([15, 25], labels=['A', 'B'])
    ax.set_xlabel("Date")
    plt.show()

示例图片

如果你想让条形更近、更窄等……你可以使用我给它们的 y 值(10,9)(20,9)值。 希望这会有所帮助 - 干杯!

暂无
暂无

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

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