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

Pandas:计算指定时间段内设备开机时长的时间差求和

设备开机天数统计解决方案

原始数据

给定记录设备开关机日期的DataFrame:

import pandas as pd

data = {
    'Date': ['2019-09-25', '2019-10-10', '2019-12-01', '2020-01-11', '2020-01-23', '2020-03-28', '2020-08-27', '2021-01-10', '2021-02-17', '2021-06-30'],
    'Action': ['Turned On', 'Turned Off', 'Turned On', 'Turned Off', 'Turned On', 'Turned Off', 'Turned On', 'Turned Off', 'Turned On', 'Turned Off']
}
df = pd.DataFrame(data)
df['Date'] = pd.to_datetime(df['Date'])

需求说明

需要计算设备在任意指定时间段(如季度、首次激活后每12个月区间)内的开机天数,核心难点是处理跨统计时段的开关机记录:

  • 开机时间早于统计时段起始,关机时间在时段内
  • 开机时间在时段内,关机时间晚于统计时段结束
  • 开机、关机时间完全覆盖统计时段

例如2019年第四季度(2019-10-01至2019-12-31)的开机天数计算:

  • 2019-10-01至2019-10-10(原开机记录为2019-09-25,需排除9月部分)
  • 2019-12-01至2019-12-31(原关机记录为2020-01-11,需排除2020年1月部分)
  • 合计40天(注:天数计算是否包含首尾可根据需求调整)

现有方法的不足

直接计算连续开关机日期的差值求和,无法处理跨时段的区间:

  • 会遗漏开机在时段前但关机在时段内的有效天数
  • 会错误统计开机在时段内但关机在时段外的多余天数

解决方案

核心思路是计算每个开关机区间与统计时段的重叠部分,求和所有有效重叠天数。

步骤1:生成开关机区间对

将原始数据中的Turned On和Turned Off记录配对,形成完整的开机-关机区间:

# 提取所有开机、关机日期
on_dates = df[df['Action'] == 'Turned On']['Date'].reset_index(drop=True)
off_dates = df[df['Action'] == 'Turned Off']['Date'].reset_index(drop=True)

# 生成区间DataFrame
interval_df = pd.DataFrame({
    'start': on_dates,
    'end': off_dates
})

步骤2:定义统计天数计算函数

编写函数处理任意时段的重叠天数计算,支持自定义是否包含首尾日期:

def calculate_on_days(intervals, period_start, period_end, include_end=True):
    # 转换为datetime类型
    period_start = pd.to_datetime(period_start)
    period_end = pd.to_datetime(period_end)
    
    # 计算每个区间与统计时段的重叠起止点
    intervals['overlap_start'] = intervals['start'].apply(lambda x: max(x, period_start))
    intervals['overlap_end'] = intervals['end'].apply(lambda x: min(x, period_end))
    
    # 计算有效重叠天数
    def get_days(row):
        if row['overlap_start'] > row['overlap_end']:
            return 0
        days_diff = (row['overlap_end'] - row['overlap_start']).days
        return days_diff + 1 if include_end else days_diff
    
    intervals['overlap_days'] = intervals.apply(get_days, axis=1)
    
    # 返回总开机天数
    return intervals['overlap_days'].sum()

步骤3:测试示例

2019年第四季度统计

q4_2019_start = '2019-10-01'
q4_2019_end = '2019-12-31'
total_q4 = calculate_on_days(interval_df, q4_2019_start, q4_2019_end)
print(f"2019年第四季度开机天数:{total_q4}")
# 输出:40(与示例一致,包含首尾日期)

2020年第一季度统计

q1_2020_start = '2020-01-01'
q1_2020_end = '2020-03-31'
total_q1 = calculate_on_days(interval_df, q1_2020_start, q1_2020_end)
print(f"2020年第一季度开机天数:{total_q1}")

自定义12月周期统计(首次激活后)

first_activation = df['Date'].min()
# 生成3个连续12月周期
periods = [
    (first_activation, first_activation + pd.DateOffset(years=1)),
    (first_activation + pd.DateOffset(years=1), first_activation + pd.DateOffset(years=2)),
    (first_activation + pd.DateOffset(years=2), first_activation + pd.DateOffset(years=3))
]

for idx, (start, end) in enumerate(periods, 1):
    days = calculate_on_days(interval_df, start, end)
    print(f"第{idx}个12月周期({start.date()} ~ {end.date()})开机天数:{days}")

方法优势

  • 支持任意时段的统计,包括季度、年度、自定义区间
  • 自动处理跨时段的开关机记录,精准计算重叠天数
  • 可通过include_end参数灵活调整天数计算规则(是否包含关机当日)

内容的提问来源于stack exchange,提问作者steliosbl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:46:07