[英]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_xranges
和a_lw
是broken_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.