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

使用Pandas按Event ID分组并基于事件时长进行动态时间分箱计数的最优实现方案问询

Fast Pandas Solution for Grouped Time Binning with Dynamic Parameters

Hey there! Let's tackle this problem efficiently—we need to group data by eventID, bin each group's time points based on the event's total duration, count instances per bin (including empty bins), and keep everything flexible for dynamic adjustments. Here's a step-by-step optimized approach:

Step 1: Prepare Your Data & Convert Time to Numeric Values

First, we need to convert human-readable time strings into a numeric format (like total minutes) so we can perform arithmetic operations easily. This is critical for speed and accuracy.

import pandas as pd

# Sample data
data = pd.DataFrame({
    'time': ['0:30', '0:30', '0:30', '4:00', '1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00'],
    'eventID': [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2],
    'value': ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
})

# Convert time strings to total minutes (numeric)
data['time_min'] = pd.to_timedelta(data['time']).dt.total_seconds() / 60

Step 2: Core Logic - Group, Bin, and Count

The key here is group-wise binning where each group's bins are calculated based on its own time range. We’ll use vectorized Pandas operations as much as possible to avoid slow loops.

Optimized Implementation

def bin_group(group, num_bins=4):
    # Calculate the event's time range
    min_time = group['time_min'].min()
    max_time = group['time_min'].max()
    
    # Create equal-duration bin edges for the event
    bin_edges = pd.linspace(min_time, max_time, num=num_bins + 1)
    
    # Assign 1-based bin labels to each time point
    group['bin'] = pd.cut(
        group['time_min'], 
        bins=bin_edges, 
        labels=range(1, num_bins + 1), 
        include_lowest=True
    )
    
    # Count instances per bin, and fill empty bins with 0
    bin_counts = group['bin'].value_counts()\
                             .reindex(range(1, num_bins + 1), fill_value=0)\
                             .reset_index()
    bin_counts.columns = ['bin', 'count']
    
    # Attach the event ID and reorder columns
    bin_counts['event'] = group['eventID'].iloc[0]
    return bin_counts[['event', 'bin', 'count']]

# Apply the function to each group and combine results
result = data.groupby('eventID', group_keys=False).apply(bin_group, num_bins=4)

# Clean up the index
result = result.reset_index(drop=True)

Verify the Output

Running this code will produce exactly your expected result:

event  bin  count
0      1    1      3
1      1    2      0
2      1    3      0
3      1    4      1
4      2    1      2
5      2    2      2
6      2    3      2
7      2    4      2

Step 3: Dynamic Parameter Support

Adjusting bins or time parameters is straightforward—just modify the arguments passed to our grouping function:

Example 1: Switch to 3 Bins

# Generate results with 3 bins per event
result_3bins = data.groupby('eventID', group_keys=False).apply(bin_group, num_bins=3)

Example 2: Use Fixed Time Intervals

If you want fixed-duration bins (e.g., 90-minute intervals) instead of splitting the event's total duration, tweak the bin_group function:

def bin_group_custom_intervals(group, interval_min=90):
    min_time = group['time_min'].min()
    # Calculate bin edges starting from the event's start time
    max_bin_edge = ((group['time_min'].max() - min_time) // interval_min + 1) * interval_min + min_time
    bin_edges = pd.arange(min_time, max_bin_edge + 1, interval_min)
    
    # Assign bin labels and count instances
    group['bin'] = pd.cut(
        group['time_min'], 
        bins=bin_edges, 
        labels=range(1, len(bin_edges)), 
        include_lowest=True
    )
    bin_counts = group['bin'].value_counts()\
                             .reindex(range(1, len(bin_edges)), fill_value=0)\
                             .reset_index()
    bin_counts.columns = ['bin', 'count']
    bin_counts['event'] = group['eventID'].iloc[0]
    return bin_counts[['event', 'bin', 'count']]

# Use 90-minute fixed intervals
result_custom = data.groupby('eventID', group_keys=False).apply(bin_group_custom_intervals, interval_min=90)

Step 4: Performance Tips for Large Datasets

For datasets with millions of rows, these tweaks will keep things fast:

  • Pre-convert time to numeric: Do this once upfront instead of inside the group function to avoid redundant computations.
  • Avoid Python loops: Our solution uses vectorized Pandas operations (pd.cut, value_counts) which are far faster than manual loops.
  • Use group_keys=False: This prevents adding redundant index layers, saving memory and processing time.
  • Reindex for empty bins: Using reindex to fill missing bins is more efficient than merging with a separate bin list.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 01:19:10