我有一个带有DateTimeIndex的pandas df,如下所示:
time
2016-06-10 10:09:16 0.0
2016-06-10 13:18:08 11332.0
2016-06-13 09:00:22 0.0
2016-06-13 10:14:12 4430.0
2016-06-13 13:27:14 11582.0
2016-06-13 15:15:59 6525.0
2016-06-13 16:25:25 4166.0
2016-06-14 09:29:23 0.0
2016-06-14 13:12:31 13388.0
2016-06-14 16:25:28 11577.0
该列显示自上次观察/行以来的秒数,并且每天都会重置,如下所示:
def time_calc(df):
res = df.index.to_series().diff().dt.seconds.fillna(0)
df = df.join(res)
return df
df = df.groupby(df.index.date, group_keys=False).apply(time_calc)
但是,我希望每天从09:00:00开始计算秒数,这样我的df应该是这样的:
time
2016-06-10 10:09:16 4156.0
2016-06-10 13:18:08 11332.0
2016-06-13 09:00:22 22.0
2016-06-13 10:14:12 4430.0
2016-06-13 13:27:14 11582.0
2016-06-13 15:15:59 6525.0
2016-06-13 16:25:25 4166.0
2016-06-14 09:29:23 1763.0
2016-06-14 13:12:31 13388.0
2016-06-14 16:25:28 11577.0
关于如何实现这一点的任何指示都将非常感激......
答案 0 :(得分:2)
我明白你现在想做什么。您可以分两步完成此操作。
首先,计算除第一个值以外的所有内容的时差。这可以通过groupby
+ shift
来完成。第一个值始终设置为NaT
,因此您可以将其设置为9:00:00
import pandas as pd
df = df.reset_index()
df['seconds'] = df.groupby(df.time.dt.date).time.apply(lambda x: x -x.shift(1))
df.loc[df.seconds.isnull(), 'seconds'] = df.loc[df.seconds.isnull(), 'time'] - pd.to_datetime(df.loc[df.seconds.isnull(), 'time'].astype('str').replace('(?<=\s).*', '9:00:00', regex=True))
df['seconds'] = df.seconds.dt.total_seconds()
df = df.set_index('time')
# seconds
#time
#2016-06-10 10:09:16 4156.0
#2016-06-10 13:18:08 11332.0
#2016-06-13 09:00:22 22.0
#2016-06-13 10:14:12 4430.0
#2016-06-13 13:27:14 11582.0
#2016-06-13 15:15:59 6525.0
#2016-06-13 16:25:25 4166.0
#2016-06-14 09:29:23 1763.0
#2016-06-14 13:12:31 13388.0
#2016-06-14 16:25:28 11577.0
答案 1 :(得分:2)
这可能不是最佳答案,但可行。
您可以使用Time Deltas来查找此内容。假设您的Pandas Dataframe或Series保存为pd.datetimes
,您可以使用pd.to_datetime()执行此操作,您可以从日期时间中减去9小时,然后获取该时间点中的所有秒数,然后以86,400为模数这是一天中的秒数。
pd.to_timedelta(df - dt.timedelta(hours=9)).dt.total_seconds() % 86400
将给出输出:
0 4156.0
1 15488.0
2 22.0
3 4452.0
4 16034.0
5 22559.0
6 26725.0
7 1763.0
8 15151.0
9 26728.0
然后你需要使用列表理解来完成它:
s2 = [x-y if d1==d2 else x for x,y,d1,d2 in zip(df.seconds[1:], df.seconds[:-1], my_days[1:], my_days[:-1])]
s2.insert(0, df.seconds[0])
4156.0
11332.0
22.0
4430.0
11582.0
6525.0
4166.0
1763.0
13388.0
11577.0
如果你希望它们是整数而不是浮点数,你可以使用。pd.DataFrame.assign()
将它分配给列(如果它是数据帧)或者如果你正在处理一个系列就创建一个数据帧。如果您希望索引成为列,只需使用df.reset_index()
。
我的互动会话如下:
import pandas as pd
import datetime as dt
time = [ "2016-06-10 10:09:16", "2016-06-10 13:18:08", "2016-06-13 09:00:22", "2016-06-13 10:14:12", "2016-06-13 13:27:14", "2016-06-13 15:15:59", "2016-06-13 16:25:25", "2016-06-14 09:29:23", "2016-06-14 13:12:31", "2016-06-14 16:25:28"]
my_time = pd.Series(time)
my_time = pd.to_datetime(my_time)
df = pd.DataFrame({
'datetime':my_time.values,
'seconds':pd.to_timedelta(my_time - dt.timedelta(hours=9)).dt.total_seconds() % 86400
})
my_days = df.datetime.dt.day
s2 = [x-y if d1==d2 else x for x,y,d1,d2 in zip(df.seconds[1:], df.seconds[:-1], my_days[1:], my_days[:-1])]
s2.insert(0, df.seconds[0])
df.loc[:, "seconds"] = s2
print(df)
datetime seconds
0 2016-06-10 10:09:16 4156.0
1 2016-06-10 13:18:08 11332.0
2 2016-06-13 09:00:22 22.0
3 2016-06-13 10:14:12 4430.0
4 2016-06-13 13:27:14 11582.0
5 2016-06-13 15:15:59 6525.0
6 2016-06-13 16:25:25 4166.0
7 2016-06-14 09:29:23 1763.0
8 2016-06-14 13:12:31 13388.0
9 2016-06-14 16:25:28 11577.0