如何在Plotly图表中展示数据负值与零值的总持续时长?
用Pandas+Plotly标注负值/零值区间时长的解决方案
一、先处理数据:找出连续的负值/零值区间并计算时长
先把time列转换成可计算的datetime类型,标记出data≤0的行,再将连续的这类行归为一组,最后算出每个区间的起止时间和持续时长:
import pandas as pd import plotly.graph_objects as go # 读取CSV,仅保留需要的两列 df = pd.read_csv('你的数据文件.csv', usecols=['time', 'data']) # 转换time列为datetime格式,否则无法计算时间差 df['time'] = pd.to_datetime(df['time']) # 按每10行抽取一行(和你之前的操作一致) df = df.loc[::10].reset_index(drop=True) # 标记data为负值或零的行 df['is_neg_zero'] = df['data'] <= 0 # 给连续的相同标记分组(核心操作:用cumsum区分不同连续区间) df['group_id'] = (df['is_neg_zero'] != df['is_neg_zero'].shift()).cumsum() # 筛选出所有负值/零值区间,计算起止时间和时长(秒) neg_intervals = df[df['is_neg_zero']].groupby('group_id').agg( start=('time', 'first'), end=('time', 'last'), duration_sec=('time', lambda x: (x.max() - x.min()).total_seconds()) ).reset_index(drop=True) # 将秒数转换为更友好的格式(如分秒、小时分) def format_time(seconds): hours = int(seconds // 3600) mins = int((seconds % 3600) // 60) secs = int(seconds % 60) if hours > 0: return f"{hours}小时{mins}分钟" elif mins > 0: return f"{mins}分钟{secs}秒" else: return f"{secs}秒" neg_intervals['duration_text'] = neg_intervals['duration_sec'].apply(format_time)
二、绘制图表并添加标注
先绘制你的折线散点图,再给每个负值/零值区间添加红色半透明阴影,最后在区间中间标注时长:
fig = go.Figure() # 绘制主数据曲线 fig.add_trace(go.Scatter( x=df['time'], y=df['data'], mode='line+markers', name='数据曲线' )) # 为每个负值/零值区间添加红色阴影和时长标注 for _, row in neg_intervals.iterrows(): # 添加红色半透明矩形阴影 fig.add_shape( type="rect", x0=row['start'], x1=row['end'], y0=df['data'].min() * 1.1, # 略低于数据最小值,确保覆盖 y1=df['data'].max() * 1.1, # 略高于数据最大值 fillcolor="red", opacity=0.2, line_width=0, ) # 计算区间中间位置,用于放置标注 mid_time = row['start'] + (row['end'] - row['start']) / 2 # 添加时长文本标注 fig.add_annotation( x=mid_time, y=df['data'].max() * 1.05, # 放在曲线上方一点的位置 text=row['duration_text'], showarrow=False, font=dict(color="red", size=10), bgcolor="white", opacity=0.8 ) # 调整图表布局 fig.update_layout( xaxis_title='时间', yaxis_title='Data值', title='数据曲线及负值/零值区间时长', showlegend=True ) # 显示图表 fig.show()
三、关键提示
- 不需要额外安装其他库,用你已经在使用的Pandas和Plotly即可完成
- 分组连续区间的核心是
cumsum()方法,它能将连续的相同状态(如均为负值/零)划分为同一组 - 时长计算依赖datetime类型的时间差,务必确保
time列转换为正确格式
内容的提问来源于stack exchange,提问作者Ganzert
相关产品推荐
相关产品推荐

