不是一个纯粹的pandas解决方案,我很确定有很多棘手的单线方法可以做到这一点,但我仍然是熊猫的基本用户。
我使用一个递归函数,duration它通过将秒数添加到连续分钟数来消耗给定值,存储为字典的键d,从 a 开始startime:
def cumsec(startime, duration, d):
if duration == 0:
return d
to_minute = (60 - startime.second)%60 if (60 - startime.second)%60 else 60
to_add = to_minute if duration - to_minute >= 0 else duration
d[startime.replace(second=0)] += to_add
startime = (startime + dt.timedelta(minutes=1)).replace(second=0)
return cumsec(startime, duration - to_add, d)
然后简单地将这个函数应用于每一行:
from collections import defaultdict
import datetime as dt
import pandas as pd
# small df arrangements
df.columns = ["VideoId", "UsageStart", "Duration"]
df["UsageStart"] = pd.to_datetime(df["UsageStart"])
d = defaultdict(int)
for r in df.itertuples():
cumsec(r.UsageStart, r.Duration, d)
为了添加可能的空分钟,您可以执行以下操作,但我确信有一个特定的方法pandas可以做到这一点(如果不需要此行为,您可以跳过此部分):
first = min(d.keys())
last = max(d.keys())
d = {
first + dt.timedelta(minutes=i): d.get(first + dt.timedelta(minutes=i), 0)
for i in range(int((last - first).total_seconds()//60) + 1)
}
最后创建一个新的DataFrame:
cumdf = pd.DataFrame({"StartTime": list(d.keys()), "UsageAmount": list(d.values())})
cumdf = cumdf.sort_values("StartTime").reset_index(drop=True)
cumdf["Minute"] = range(1, len(d) + 1)
print(cumdf)
因此,如果您的输入是:
Video-ID | UsageStart | Duration
459224 | 2019-04-24 23:59:59 | 2
260581 | 2019-04-25 00:00:00 | 10
316288 | 2019-04-25 00:01:05 | 20
791714 | 2019-04-25 00:01:30 | 10
790503 | 2019-04-25 00:02:30 | 90
646034 | 2019-04-25 00:03:10 | 100
934784 | 2019-04-25 00:09:10 | 40
输出将是:
StartTime UsageAmount Minute
0 2019-04-24 23:59:00 1 1
1 2019-04-25 00:00:00 11 2
2 2019-04-25 00:01:00 30 3
3 2019-04-25 00:02:00 30 4
4 2019-04-25 00:03:00 110 5
5 2019-04-25 00:04:00 50 6
6 2019-04-25 00:05:00 0 7
7 2019-04-25 00:06:00 0 8
8 2019-04-25 00:07:00 0 9
9 2019-04-25 00:08:00 0 10
10 2019-04-25 00:09:00 40 11