You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:51:17