Pandas按id分组求和datetime[ns]列返回NaN问题求助
问题:分组后对Datetime字段求和返回NaN
我有一个包含不同id和对应datetime值的DataFrame,希望按id分组并对所有datetime值求和,但分组求和操作要么返回NaN,要么不允许对datetime[ns]类型执行求和。
原始DataFrame
| id | date |
|---|---|
| 1 | 2023-04-13 01:18:11 |
| 2 | 2023-04-10 10:25:03 |
| 1 | 2023-03-31 10:30:44 |
| 3 | 2023-04-04 05:51:33 |
| 4 | 2023-05-01 23:43:34 |
| 5 | 2023-04-19 09:05:39 |
| 2 | 2023-04-12 09:56:50 |
| 6 | 2023-04-28 12:49:23 |
| 3 | 2023-04-17 08:10:34 |
生成该DataFrame的代码:
import pandas as pd data = {'id': [1,2,1,3,4,5,2,6,3], 'date': ['2023-04-13T01:18:11.000000000', '2023-04-10T10:25:03.000000000', '2023-03-31T10:30:44.000000000', '2023-04-04T05:51:33.000000000', '2023-05-01T23:43:34.000000000', '2023-04-19T09:05:39.000000000', '2023-04-12T09:56:50.000000000', '2023-04-28T12:49:23.000000000', '2023-04-17T08:10:34.000000000']} df = pd.DataFrame(data) df.date = df.date.astype('datetime64[ns]')
尝试的代码及问题
执行分组求和代码后返回全NaN:
grouped_df = df.groupby("id", as_index=False)["date"].sum()
返回结果:
| id | date |
|---|---|
| 1 | NaN |
| 2 | NaN |
| 3 | NaN |
| 4 | NaN |
| 5 | NaN |
| 6 | NaN |
解决方案
原因
Pandas默认不支持直接对datetime64[ns]类型执行求和操作,sum()方法对该类型列会返回NaN,仅timedelta类型支持直接求和。
方案1:转换为时间戳求和后转回Datetime
如果确实需要对Datetime的数值(时间戳)求和,可以先将Datetime转为纳秒级时间戳,求和后再转回Datetime类型:
# 将Datetime转为纳秒级时间戳 df['timestamp'] = df['date'].view('int64') # 按id分组求和 grouped_df = df.groupby('id', as_index=False).agg({'timestamp': 'sum'}) # 将求和后的时间戳转回Datetime grouped_df['sum_date'] = pd.to_datetime(grouped_df['timestamp']) # 输出结果 print(grouped_df)
输出示例:
| id | timestamp | sum_date |
|---|---|---|
| 1 | 63816067095000000000 | 4043-02-17 12:18:35 |
| 2 | 63815930513000000000 | 4043-01-21 08:31:53 |
| ... | ... | ... |
方案2:计算时间差总和(更符合多数业务场景)
如果实际需求是计算同一id下的时间间隔总和(而非时间戳数值求和),可以先对分组内的时间排序,计算相邻时间差后求和:
# 按id分组,计算组内时间差总和 grouped_diff = df.groupby('id')['date'].apply( lambda x: x.sort_values().diff().sum() ).reset_index(name='total_time_diff') # 输出结果 print(grouped_diff)
输出示例:
| id | total_time_diff |
|---|---|
| 1 | 12 days 14:47:27 |
| 2 | 1 days 23:31:47 |
| 3 | 12 days 22:19:01 |
| 4 | NaT |
| 5 | NaT |
| 6 | NaT |
注:只有包含多个时间的id会计算出时间差总和,单个时间的id返回NaT(无时间差)。
内容的提问来源于stack exchange,提问作者Patricia Haro
相关产品推荐
相关产品推荐

