【问题标题】:Calculate the duration of overlapping time ranges using pandas使用 pandas 计算重叠时间范围的持续时间
【发布时间】:2015-09-16 17:59:42
【问题描述】:

我有类似于以下示例的大型 csv 流量数据文件,我需要为此计算总字节数和每次数据传输的持续时间。 时间范围重叠,但必须合并:

first_packet_ts last_packet_ts  bytes_uplink bytes_downlink service    user_id
1441901695012   1441901696009       165             1212    facebook    3
1441901695500   1441901696212        23             4321    facebook    3
1441901698000   1441901698010       242             3423    youtube     4
1441901698400   1441901698500       423             2344    youtube     4

期望的输出:

 duration     bytes_uplink      bytes_downlink    service          user_id
   1200             188             5533          facebook            3
   110              665             5767          youtube             4   

我目前使用类似于以下几行的内容:

df = pd.read_csv(input_file_path)
df = df.groupby(['service', 'user_id'])
durations = df.apply(calculate_duration) 
df = df[['bytes_uplink', 'bytes_downlink']].sum()
df = df.reset_index()

calculate_duration 函数(下)迭代每个的内容 组,合并重叠的时间间隔,然后返回一个数据帧,然后将其连接到求和的数据帧 df。

def calculate_duration(group):
    ranges = group[['first_packet_ts', 'last_packet_ts']].itertuples()
    duration = 0
    for i,current_start, current_stop in ranges:
        for i, start, stop in ranges:
            if start > current_stop:
                duration += current_stop - current_start
                current_start, current_stop = start, stop
            else:
                current_stop = max(current_stop, stop)
        duration += current_stop - current_start
    return duration

这种方法非常慢,因为它涉及迭代并为每个组调用 apply 方法。

有没有更有效的方法来计算数据传输的持续时间,合并重叠间隔,使用 pandas(以某种方式避免迭代?)最好不求助于 cython?

【问题讨论】:

  • 你能显示calculate_duration吗?
  • 我添加了我的 calculate_duration 函数的一个版本。但是我认为目标不是优化函数,而是如果可能的话,在不使用 apply() 的情况下进行计算。 (即使函数为空,对性能的影响也很大)

标签: python numpy pandas interval-arithmetic


【解决方案1】:

这个怎么样? (已经计时了,可能会慢一点……)

pd.pivot_table(df, columns='user_id', index='service',
               values=['bytes_uplink', 'bytes_downlink'], aggfunc=sum)

编辑:我不认为这比你的更有效,但你可以尝试以下方式:

# create dummy start/end dataframe
df = pd.DataFrame({'end':pd.Series([50, 100, 120, 150]), 'start':pd.Series([30, 0, 40, 130])})
df = df[['start', 'end']]
df = df.sort('start')

df['roll_end'] = df.end.cummax()
df.roll_end = df.roll_end.shift()

df['new_start'] = df.start
overlap = df.start - df.roll_end < 0
# if start is before rolling max end time then reset start to rolling max end time
df.new_start[overlap] = df.roll_end[overlap]

# if the new start is after end, then completely overlapping
print np.sum([x for x in df.end - df.new_start if x > 0])

【讨论】:

  • 谢谢,但是问题是关于如何计算组合在一起的重叠间隔的持续时间。
  • @GeorgeV。好的,对不起,我只是想重现您的结果。你可以只使用每组中最大/最小最后/第一的差异吗?对我来说似乎更有意义,但我显然不知道你的最终目标是什么。
  • 最终目标是计算每个服务的吞吐量。在这种情况下,使用每组的最大/最小最后/第一个的差异是没有意义的,因为它只考虑了第一个和最后一个看到的数据包。我希望 pandas 或 numpy 具有这样的功能,可以轻松地进行此类计算而无需迭代。
  • @GeorgeV。稍微考虑一下,并意识到使用 cummax() 而不是滚动最大值。已更新答案。
【解决方案2】:

下面的代码根据示例数据重现了您的输出。这就是你要找的吗?

>>> df.groupby(['service', 'user_id'])['bytes_uplink', 'bytes_downlink'].sum().reset_index()
    service  user_id  bytes_uplink  bytes_downlink
0  facebook        3           188            5533
1   youtube        4           665            5767

【讨论】:

  • 否,输出必须包含时间间隔的持续时间。问题是时间间隔可能重叠,所以我不能简单地总结每一行的持续时间。
  • 也许您应该更新您的示例数据。在示例数据上运行代码会产生相同的结果。 How to Ask
  • 是的,我没有表明我将calculate_duration的结果与上面代码中的聚合结果合并。我会更新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 2015-10-30
  • 1970-01-01
相关资源
最近更新 更多