在折线图上绘制事件

Plotting events on a line graph

我正在尝试使用数据框中包含的数据可视化降雨事件。 这个想法看似很简单,但执行起来似乎是不可能的! 这是数据框的一部分:

         start_time             end_time      duration      br_open_total
0   2022-01-01 10:00:00 2022-01-01 19:00:00     9.0       0.2540000563879943
1   2022-01-02 00:00:00 2022-01-02 10:00:00    10.0       1.0160002255520624
2   2022-01-02 17:00:00 2022-01-03 02:00:00     9.0       0.7620001691640113
3   2022-01-03 02:00:00 2022-01-04 12:00:00    34.0      10.668002368296513
4   2022-01-07 21:00:00 2022-01-08 06:00:00     9.0       0.2540000563879943
5   2022-01-16 05:00:00 2022-01-16 20:00:00    15.0       0.5080001127760454
6   2022-01-19 04:00:00 2022-01-19 17:00:00    13.0       0.7620001691640255
7   2022-01-21 14:00:00 2022-01-22 00:00:00    10.0       1.5240003383280751
8   2022-01-27 02:00:00 2022-01-27 16:00:00    14.0       3.0480006766561503
9   2022-02-01 12:00:00 2022-02-01 21:00:00     9.0       0.2540000563880126
10  2022-02-03 05:00:00 2022-02-03 15:00:00    10.0       0.5080001127760251

我想要做的是在 x 轴上绘制时间,在 y 轴上绘制 'br_open_total' 的值。

我可以画出我想要的样子,见下图:

对于绘图的简单性,我深表歉意,但我认为它解释了我想做的事情。 我该怎么做,然后在同一地块上重复其他数据帧。 我试过楼梯,matplotlib.pyplot.stair 和其他人都没有成功。

好像是个简单的概念!

编辑 1:

用实际数据尝试了 Joswin KJ 的回答,得到了这个:

02-12 11:00 的事件应该持续 112 小时,但条形图与其他所有条形图的宽度相同。

编辑2: 尝试了 Mozway 的回答并得到了这个:

仍然不显示每个事件的宽度,也不离散化事件

编辑 3: 使用 Mozway 的修改后的答案,我得到了实际数据的这个图: 我使用 paint 添加了光标位置,在图的右上角你可以看到光标位于 2022-02-09 和 20.34,这实际上是 2022-02-01 的值,所以看起来图向左移动了一个数据点?,而且 2022-3-01 和 2022-04-03 之间的大块似乎不在数据中

编辑 4:根据 Mozway 的要求

重塑数据

    duration    br_open_total       variable          date
0   10.0      1.0160002255520624     start_time     2022-01-02 00:00:00
19  10.0            0.0              end_time       2022-01-02 10:00:00
1   9.0       0.7620001691640113     start_time     2022-01-02 17:00:00
2   34.0     10.668002368296513      start_time     2022-01-03 02:00:00
21  34.0          0.0                end_time       2022-01-04 12:00:00
3   15.0      0.5080001127760454     start_time     2022-01-16 05:00:00
22  15.0           0.0               end_time       2022-01-16 20:00:00
4   13.0      0.7620001691640255     start_time     2022-01-19 04:00:00
23  13.0           0.0               end_time       2022-01-19 17:00:00
5   10.0      1.5240003383280751     start_time     2022-01-21 14:00:00
24  10.0           0.0               end_time       2022-01-22 00:00:00
6   14.0      3.0480006766561503     start_time     2022-01-27 02:00:00
25  14.0           0.0               end_time       2022-01-27 16:00:00
7   10.0      0.5080001127760251     start_time     2022-02-03 05:00:00
26  10.0           0.0               end_time       2022-02-03 15:00:00
8   18.0      7.366001635252363      start_time     2022-02-03 23:00:00
27  18.0           0.0               end_time       2022-02-04 17:00:00
9   13.0      2.28600050749211       start_time     2022-02-05 11:00:00
28  13.0           0.0               end_time       2022-02-06 00:00:00
10  19.0      2.2860005074921173     start_time     2022-02-06 04:00:00
29  19.0           0.0               end_time       2022-02-06 23:00:00
11  13.0      1.2700002819400584     start_time     2022-02-07 11:00:00
30  13.0           0.0               end_time       2022-02-08 00:00:00
12  12.0      2.79400062026814       start_time     2022-02-09 01:00:00
31  12.0           0.0               end_time       2022-02-09 13:00:00
13  112.0    20.320004511041         start_time     2022-02-12 11:00:00
32  112.0          0.0               end_time       2022-02-17 03:00:00
14  28.0      2.0320004511041034     start_time     2022-02-18 14:00:00
33  28.0           0.0               end_time       2022-02-19 18:00:00
15  17.0     17.272003834384847      start_time     2022-02-23 17:00:00
34  17.0           0.0               end_time       2022-02-24 10:00:00
16  9.0       0.7620001691640397     start_time     2022-02-27 13:00:00
35  9.0            0.0               end_time       2022-02-27 22:00:00
17  18.0      4.0640009022082        start_time     2022-04-04 00:00:00
36  18.0           0.0               end_time       2022-04-04 18:00:00
18  15.0      1.0160002255520482     start_time     2022-04-06 05:00:00
37  15.0           0.0               end_time       2022-04-06 20:00:00

使用

绘制时
plt.step(bdf2['date'], bdf2['br_open_total'])
plt.gcf().set_size_inches(10, 4)
plt.xticks(rotation=90)

生成如上所示的图,其中块的左上角对应于前一个数据点。

编辑 5:更多信息 当我绘制我所有的数据帧(不同的传感器)时,我在事件开始和结束时间上得到相同的差异?

试试这个:

import matplotlib.pyplot as plt

for ind,row in df.iterrows():
    plt.plot(pd.Series([row['start_time'],row['end_time']]),pd.Series([row['br_open_total'],row['br_open_total']]),color='b')
    plt.plot(pd.Series([row['start_time'],row['start_time']]),pd.Series([0,row['br_open_total']]),color='b')
    plt.plot(pd.Series([row['end_time'],row['end_time']]),pd.Series([0,row['br_open_total']]),color='b')
plt.xticks(rotation=90)

结果:

您可以使用 step 图:

# ensure datetime
df['start_time'] = pd.to_datetime(df['start_time'])
df['end_time'] = pd.to_datetime(df['end_time'])

# reshape the data
df2 = (df
 .melt(id_vars=['duration', 'br_open_total'], value_name='date')
 .sort_values(by='date')
 .drop_duplicates(subset='date')
 .assign(br_open_total=lambda d: d['br_open_total'].mask(d['variable'].eq('end_time'), 0))
)

# plot
import matplotlib.pyplot as plt
plt.step(df2['date'], df2['br_open_total'])
plt.gcf().set_size_inches(10, 4)

输出:

重塑数据:

    duration  br_open_total    variable                date
0        9.0       0.254000  start_time 2022-01-01 10:00:00
11       9.0       0.000000    end_time 2022-01-01 19:00:00
1       10.0       1.016000  start_time 2022-01-02 00:00:00
12      10.0       0.000000    end_time 2022-01-02 10:00:00
2        9.0       0.762000  start_time 2022-01-02 17:00:00
3       34.0      10.668002  start_time 2022-01-03 02:00:00
14      34.0       0.000000    end_time 2022-01-04 12:00:00
4        9.0       0.254000  start_time 2022-01-07 21:00:00
15       9.0       0.000000    end_time 2022-01-08 06:00:00
5       15.0       0.508000  start_time 2022-01-16 05:00:00
16      15.0       0.000000    end_time 2022-01-16 20:00:00
6       13.0       0.762000  start_time 2022-01-19 04:00:00
17      13.0       0.000000    end_time 2022-01-19 17:00:00
7       10.0       1.524000  start_time 2022-01-21 14:00:00
18      10.0       0.000000    end_time 2022-01-22 00:00:00
8       14.0       3.048001  start_time 2022-01-27 02:00:00
19      14.0       0.000000    end_time 2022-01-27 16:00:00
9        9.0       0.254000  start_time 2022-02-01 12:00:00
20       9.0       0.000000    end_time 2022-02-01 21:00:00
10      10.0       0.508000  start_time 2022-02-03 05:00:00
21      10.0       0.000000    end_time 2022-02-03 15:00:00

我相信我现在已经破解了它,非常感谢@Mozway。 重构绘图数据框的代码:

#create dataframes of each open gauge events removing any event with an open total of less than 0.254mm
#bresser/open
bdftdf=bdf.loc[bdf['br_open_total'] > 0.255]
bdftdf=bdftdf.copy()
bdftdf['start_time'] = pd.to_datetime(bdftdf['start_time'])
bdftdf['end_time'] = pd.to_datetime(bdftdf['end_time'])
bdf2 = (bdftdf
  .melt(id_vars=['duration', 'ic_total','mc_total','md_total','imd_total','oak_total','highpoint_total','school_total','br_open_total',
                'fr_gauge_total','open_mean_total','br_open_ic_%_int','br_open_mc_%_int','br_open_md_%_int','br_open_imd_%_int',
                'br_open_oak_%_int'], value_name='date')
  .sort_values(by='date')
  #.drop_duplicates(subset='date')
  .assign(br_open_total=lambda d: d['br_open_total'].mask(d['variable'].eq('end_time'), 0))
)
#create array for stairs plot
bdfarr=np.array(bdf2['date'])
bl=len(bdf2)
bdfarr=np.append(bdfarr,[bdfarr[bl-1]+np.timedelta64(1,'h')])

我没有使用 Mozway 建议的 plt.step 图,而是使用了 plt.stairs,在数据框中创建了 'date' 列的数组并将一个额外的元素附加到该数组等于最后一个元素 = 1 小时。 这意味着数据现在按照我的预期绘制。:

情节代码:

fig1=plt.figure()
plt.stairs(bdf2['br_open_total'], bdfarr, label='Bresser\Open')
plt.stairs(frdf2['fr_gauge_total'], frdfarr, label='FR Gauge')
plt.stairs(hpdf2['highpoint_total'], hpdfarr, label='Highpoint')
plt.stairs(schdf2['school_total'], schdfarr, label='School')
plt.stairs(opmedf2['open_mean_total'], opmedfarr, label='Open mean')
plt.xticks(rotation=90)
plt.legend(title='Rain events', loc='best')
plt.show()