Pandas 根据另一列的日期时间值填充一列的缺失值

Pandas fill missing values of a column based on the datetime values of another column

Python新手,这是我的第一个问题。 我试图找到类似 SO 问题的解决方案,例如 , , and also ,但我认为我的问题有所不同。

这是我的情况:我有一个非常大的数据集,包含两列:Date(日期时间对象)和 session_id (整数)。时间戳指的是在线会话期间某个动作发生的时刻。

我的问题是我有所有日期,但缺少一些相应的 session_id 值。我想做的是使用日期列填充这些缺失值:

  1. 如果操作发生在某个会话的第一个日期和最后一个日期之间,我想用那个会话的 ID 填充缺失值。
  2. 我会将操作发生在任何会话范围之外的会话标记为“0”-
  3. 如果无法将事件关联到单个会话,则将其标记为'-99',因为它发生在不同会话的时间范围内。

为了举例说明我的问题,让我们考虑下面的玩具数据集,其中我只有三个会话:a、b、c。会话 a 和 b 注册了三个事件,会话 c 两个。此外,我缺少三个 id 值。

   |       DATE          |sess_id|
----------------------------------
 0 | 2018-01-01 00:19:01 | a    | 
 1 | 2018-01-01 00:19:05 | b    | 
 2 | 2018-01-01 00:21:07 | a    |
 3 | 2018-01-01 00:22:07 | b    | 
 4 | 2018-01-01 00:25:09 | c    |         
 5 | 2018-01-01 00:25:11 | Nan  |
 6 | 2018-01-01 00:27:28 | c    | 
 7 | 2018-01-01 00:29:29 | a    | 
 8 | 2018-01-01 00:30:35 | Nan  | 
 9 | 2018-01-01 00:31:16 | b    | 
10 | 2018-01-01 00:35:22 | Nan  | 
...

[Image_Timeline example][1]

这是我想要得到的:

   |       DATE          |sess_id|
----------------------------------
 0 | 2018-01-01 00:19:01 | a    | 
 1 | 2018-01-01 00:19:05 | b    | 
 2 | 2018-01-01 00:21:07 | a    |
 3 | 2018-01-01 00:22:07 | b    | 
 4 | 2018-01-01 00:25:09 | c    |         
 5 | 2018-01-01 00:25:11 | -99  |
 6 | 2018-01-01 00:27:28 | c    | 
 7 | 2018-01-01 00:29:29 | a    | 
 8 | 2018-01-01 00:30:35 | b    | 
 9 | 2018-01-01 00:31:16 | b    | 
10 | 2018-01-01 00:35:22 | 0    | 
...

通过这种方式,我将能够在没有会话代码的情况下至少恢复一些事件。 我认为也许要做的第一件事是计算两个新列,显示每个会话的第一个和最后一个时间值,类似这样:

foo['last'] = foo.groupby('sess_id')['DATE'].transform(max) 
foo['firs'] = foo.groupby('SESSIONCODE')['DATE'].transform(min) 

然后使用first-last时间值来检查每个session id未知的事件是否在该范围内。

你的直觉对我来说似乎很好,但你不能以这种方式应用它,因为你的数据框 foo 的大小与你的 groupby 数据框的大小不同。您可以做的是像这样映射值:

foo['last'] = foo.sess_id.map(foo.groupby('sess_id').DATE.max())
foo['first'] = foo.sess_id.map(foo.groupby('sess_id').DATE.min())

但我认为没有必要,您可以直接使用 groupby 数据框。

解决您的问题的一种方法是在 sess_id 列中查找缺失值,并将自定义函数应用于相应的日期:

def my_custom_function(time):
    current_sessions = my_agg.loc[(my_agg['min']<time) & (my_agg['max']>time)]
    count = len(current_sessions)
    if count == 0:
        return 0
    if count > 1:
        return -99
    return current_sessions.index[0]

my_agg = foo.groupby('sess_id').DATE.agg([min,max])
foo.loc[foo.sess_id.isnull(),'sess_id'] = foo.loc[foo.sess_id.isnull(),'DATE'].apply(my_custom_function)

输出:

    DATE                    sess_id
0   2018-01-01 00:19:01     a
1   2018-01-01 00:19:05     b
2   2018-01-01 00:21:07     a
3   2018-01-01 00:22:07     b
4   2018-01-01 00:25:09     c
5   2018-01-01 00:25:11     -99
6   2018-01-01 00:27:28     c
7   2018-01-01 00:29:29     a
8   2018-01-01 00:30:35     b
9   2018-01-01 00:31:16     b
10  2018-01-01 00:35:22     0

我认为它执行了您正在寻找的内容,尽管您在问题中发布的输出似乎包含拼写错误。