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

如何用Pandas对时长数据框分桶?大内存数据优化方案咨询

Pandas时间跨度分桶实现及大内存优化方案

问题背景

需要对包含时间戳(ts)和时长(dur)的DataFrame按跨度3进行分桶,统计每个分桶内的总时长,同时解决大时间范围(如纳秒单位)下的内存溢出问题。

示例数据:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'ts':   [1, 5, 10, 12],
    'dur':  [1, 2,  6, 6],
})

预期输出:

bin1, 1
bin2, 2
bin3, 0
bin4, 4
bin5, 6
bin6, 2

基础实现方案(小数据量适用)

核心思路是生成完整分桶区间,计算每条数据与分桶的交集时长后汇总:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'ts':   [1, 5, 10, 12],
    'dur':  [1, 2,  6, 6],
})

# 计算每条数据的时间起止区间
df['start'] = df['ts']
df['end'] = df['ts'] + df['dur']

# 定义分桶参数
bin_size = 3
min_start = df['start'].min()
max_end = df['end'].max()

# 生成所有分桶的区间索引
bin_starts = np.arange(min_start, max_end + bin_size, bin_size)
bins = pd.IntervalIndex.from_arrays(bin_starts[:-1], bin_starts[1:], closed='left')

# 计算单条数据与所有分桶的交集时长
def calculate_overlap(row):
    row_start, row_end = row['start'], row['end']
    overlap_start = np.maximum(bins.left, row_start)
    overlap_end = np.minimum(bins.right, row_end)
    return np.maximum(0, overlap_end - overlap_start)

# 汇总所有分桶的总时长
overlap_matrix = df.apply(calculate_overlap, axis=1)
bin_totals = overlap_matrix.sum(axis=0)

# 格式化输出结果
result = pd.Series(bin_totals.values, index=[f'bin{i+1}' for i in range(len(bin_totals))])
print(result.to_csv(sep=',', header=False))

大内存优化方案(稀疏处理)

当时间单位为纳秒、数据量较大时,全量分桶会生成巨量数组导致内存溢出,此时采用稀疏处理,仅计算有数据交集的分桶:

import pandas as pd
import numpy as np
from collections import defaultdict

df = pd.DataFrame({
    'ts':   [1, 5, 10, 12],
    'dur':  [1, 2,  6, 6],
})

bin_size = 3
df['start'] = df['ts']
df['end'] = df['ts'] + df['dur']

min_start = df['start'].min()
max_end = df['end'].max()

# 计算分桶的最小/最大索引
min_bin_idx = 0
max_bin_idx = ((max_end - min_start - 1) // bin_size)

# 用字典累加分桶时长(仅存储有数据的分桶)
bin_duration = defaultdict(int)

for _, row in df.iterrows():
    s, e = row['start'], row['end']
    if s >= e:
        continue
    
    # 计算当前区间覆盖的分桶索引范围
    idx_start = ((s - min_start) // bin_size)
    idx_end = ((e - min_start - 1) // bin_size)
    
    if idx_start == idx_end:
        # 仅覆盖单个分桶
        bin_duration[idx_start] += e - s
    else:
        # 累加第一个分桶的部分时长
        first_bin_end = min_start + (idx_start + 1)*bin_size
        bin_duration[idx_start] += first_bin_end - s
        # 累加中间完整分桶的时长
        for idx in range(idx_start + 1, idx_end):
            bin_duration[idx] += bin_size
        # 累加最后一个分桶的部分时长
        last_bin_start = min_start + idx_end*bin_size
        bin_duration[idx_end] += e - last_bin_start

# 生成包含空分桶的完整结果
for idx in range(min_bin_idx, max_bin_idx + 1):
    print(f'bin{idx+1}, {bin_duration.get(idx, 0)}')

进一步内存优化

若需存储结果,可转为Pandas稀疏序列,仅保存非0值:

idx_list = list(range(min_bin_idx, max_bin_idx + 1))
val_list = [bin_duration.get(idx, 0) for idx in idx_list]
sparse_series = pd.SparseSeries(val_list, index=[f'bin{idx+1}' for idx in idx_list], fill_value=0)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 09:19:53