[英]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.