合并数据帧对象和timedelta64



我有一个dtype datetime64 的数据帧

df:
time           timestamp
18053.401736   2019-06-06 09:38:30+00:00
18053.418252   2019-06-06 10:02:17+00:00
18053.424514   2019-06-06 10:11:18+00:00
18053.454132   2019-06-06 10:53:57+00:00
Name: timestamp, dtype: datetime64[ns, UTC]

和一系列dtype timedelta64

ss:
ref_time
0 days 09:00:00
1       0 days 09:00:01
2       0 days 09:00:02
3       0 days 09:00:03
4       0 days 09:00:04
...      
21596   0 days 14:59:56
21597   0 days 14:59:57
21598   0 days 14:59:58
21599   0 days 14:59:59
21600   0 days 15:00:00
Name: timeonly, Length: 21601, dtype: timedelta64[ns]

我想将两者合并,以便输出df只有在时间戳和系列一致的地方才有值:

Desired output:
time           timestamp                     ref_time
Nan            Nan                           09:00:00
...            ...                           ...
Nan            Nan                           09:38:29
18053.401736   2019-06-06 09:38:30+00:00     09:38:30
Nan            Nan                           09:38:31
...            ...                           ...
18053.418252   2019-06-06 10:02:17+00:00     10:02:17
Nan            Nan                           10:02:18
Nan            Nan                           10:02:19
...            ...                           ...
18053.424514   2019-06-06 10:11:18+00:00     10:11:18
...            ...                           ...
18053.454132   2019-06-06 10:53:57+00:00     10:53:57

然而,如果我将"timestamp"转换为一个时间,我只会得到一个对象dtype,并且无法将其与ss合并。

dframe['timestamp'].dtype        # --> datetime64[ns, UTC]
df['timeonly'] = df['timestamp'].dt.time 
df['timeonly'].dtype             # --> object
df_date.merge(timeax, how='outer', on=['timeonly'])
# ValueError: You are trying to merge on object and timedelta64[ns] columns. If you wish to proceed you should use pd.concat

但是按照建议使用concat并不能给我所需的输出。如何合并/连接DataFrame和Series?Pandas 1.1.5版

通过减去日期部分将时间戳转换为时间增量,然后合并:

df1 = pd.DataFrame([pd.Timestamp('2019-06-06 09:38:30+00:00'),pd.Timestamp('2019-06-06 10:02:17+00:00')], columns=['timestamp'])
df2 = pd.DataFrame([pd.Timedelta('09:38:30')], columns=['ref_time'])
timestamp                  
0   2019-06-06 09:38:30+00:00
1   2019-06-06 10:02:17+00:00
timestamp    datetime64[ns, UTC]
dtype: object
ref_time
0   09:38:30
ref_time    timedelta64[ns]
dtype: object
df1['merge_key'] = df1['timestamp'].dt.tz_localize(None) - pd.to_datetime(df1['timestamp'].dt.date)
df_merged = df1.merge(df2, left_on = 'merge_key', right_on = 'ref_time')

提供:

timestamp                   merge_key   ref_time
0   2019-06-06 09:38:30+00:00   09:38:30    09:38:30

这里的主要挑战是将所有内容转换为兼容的日期类型。使用您稍微修改过的示例作为输入

from io import StringIO
df = pd.read_csv(StringIO(
"""
time,timestamp
18053.401736,2019-06-06 09:38:30+00:00
18053.418252,2019-06-06 10:02:17+00:00
18053.424514,2019-06-06 10:11:18+00:00
18053.454132,2019-06-06 10:53:57+00:00
"""))
df['timestamp'] = pd.to_datetime(df['timestamp'])
from datetime import timedelta
sdf = pd.read_csv(StringIO(
"""
ref_time
0 days 09:00:00
0 days 09:00:01
0 days 09:00:02
0 days 09:00:03
0 days 09:00:04
0 days 09:38:30
0 days 10:02:17
0 days 14:59:56
0 days 14:59:57
0 days 14:59:58
0 days 14:59:59
0 days 15:00:00
"""))
sdf['ref_time'] = pd.to_timedelta(sdf['ref_time'])

这里的数据类型与您的问题一样,哪个是重要的

首先,我们计算出base_date,因为我们需要将时间增量转换为日期时间等。注意,我们通过round('1d')将其设置为相关日期的午夜

base_date = df['timestamp'].iloc[0].round('1d').to_pydatetime()
base_date

输出

datetime.datetime(2019, 6, 6, 0, 0, tzinfo=<UTC>)

接下来,我们将sdf的时间增量添加到base_date:

sdf['ref_dt'] = sdf['ref_time'] + base_date

现在sdf['ref_dt']df['timestamp']在同一个"单元"中,属于同一类型,所以我们可以合并

sdf.merge(df, left_on = 'ref_dt', right_on = 'timestamp', how = 'left')

输出

ref_time         ref_dt                        time  timestamp
--  ---------------  -------------------------  -------  -------------------------
0  0 days 09:00:00  2019-06-06 09:00:00+00:00    nan    NaT
1  0 days 09:00:01  2019-06-06 09:00:01+00:00    nan    NaT
2  0 days 09:00:02  2019-06-06 09:00:02+00:00    nan    NaT
3  0 days 09:00:03  2019-06-06 09:00:03+00:00    nan    NaT
4  0 days 09:00:04  2019-06-06 09:00:04+00:00    nan    NaT
5  0 days 09:38:30  2019-06-06 09:38:30+00:00  18053.4  2019-06-06 09:38:30+00:00
6  0 days 10:02:17  2019-06-06 10:02:17+00:00  18053.4  2019-06-06 10:02:17+00:00
7  0 days 14:59:56  2019-06-06 14:59:56+00:00    nan    NaT
8  0 days 14:59:57  2019-06-06 14:59:57+00:00    nan    NaT
9  0 days 14:59:58  2019-06-06 14:59:58+00:00    nan    NaT
10  0 days 14:59:59  2019-06-06 14:59:59+00:00    nan    NaT
11  0 days 15:00:00  2019-06-06 15:00:00+00:00    nan    NaT

我们看到合并发生在需要的地方