Python 创建一个新列,其中包含自上次事件以来的时间

Python 创建一个新列,其中包含自上次事件以来的时间,python,python-3.x,pandas,Python,Python 3.x,Pandas,我有一个具有以下结构的熊猫数据帧: ID date event_1 event_2 1 2016-01-03 False False 2016-02-07 True False 2016-02-18 False True 2 2016-01-01 False True 2016-01-04 False False 201

我有一个具有以下结构的熊猫数据帧:

ID    date           event_1   event_2 
 1    2016-01-03     False     False
      2016-02-07     True      False
      2016-02-18     False     True
 2    2016-01-01     False     True
      2016-01-04     False     False
      2016-02-02     True      False
      2016-02-04     False     False
      2016-02-05     False     True
ID
date
是一个
多索引

问题是,我想创建两个新列
time\u 1
time\u 2
。这些列应显示自相应事件以来经过的时间,例如

ID    date           event_1     event_2   time_1    time_2
 1    2016-01-03     False       False     -          -
      2016-02-07     True        False     0          -
      2016-02-18     False       True      11         0
 2    2016-01-01     False       True      -          0
      2016-01-04     False       False     -          3
      2016-02-02     True        False     0          32
      2016-02-04     False       False     2          34
      2016-02-05     False       True      3          0
如果日期是一个索引,我如何创建一个函数来计算
pandas


根据
ID
进行计算,且事件无关

如果重置索引,使ID和date成为列(只是为了方便引用--
df.index.get_level_values(“date”)
有点笨拙),并且确保df[“date”]是一个实时列而不是字符串,我认为这非常简单:

df["time_1"] = df["date"] - df["date"].where(df["event_1"]).groupby(df["ID"]).ffill()
df["time_2"] = df["date"] - df["date"].where(df["event_2"]).groupby(df["ID"]).ffill()
给我

In [173]: df
Out[173]: 
   ID       date  event_1  event_2  time_1  time_2
0   1 2016-01-03    False    False     NaT     NaT
1   1 2016-02-07     True    False  0 days     NaT
2   1 2016-02-18    False     True 11 days  0 days
3   2 2016-01-01    False     True     NaT  0 days
4   2 2016-01-04    False    False     NaT  3 days
5   2 2016-02-02     True    False  0 days 32 days
6   2 2016-02-04    False    False  2 days 34 days
7   2 2016-02-05    False     True  3 days  0 days
这是因为(使用event_2,因为它有两个不同的Trues,所以更有趣)首先,我们只选择“开始”时间:

然后我们按ID分组,并提前填写参考日期:

In [177]: df["date"].where(df["event_2"]).groupby(df["ID"]).ffill()
Out[177]: 
0          NaT
1          NaT
2   2016-02-18
3   2016-01-01
4   2016-01-01
5   2016-01-01
6   2016-01-01
7   2016-02-05
Name: date, dtype: datetime64[ns]
在这之后,我们只需要减去得到时间差。你可以用

df["time_1"] = df["time_1"].dt.days
df["time_2"] = df["time_2"].dt.days

如果您愿意,可以使用浮点而不是时间增量。

如果您重置索引,使ID和日期成为列(只是为了更方便地引用它们--
df.index.get_level_values(“date”)
有点笨拙),并且确保df[“date”]是一个实时列而不是字符串,我认为这非常简单:

df["time_1"] = df["date"] - df["date"].where(df["event_1"]).groupby(df["ID"]).ffill()
df["time_2"] = df["date"] - df["date"].where(df["event_2"]).groupby(df["ID"]).ffill()
给我

In [173]: df
Out[173]: 
   ID       date  event_1  event_2  time_1  time_2
0   1 2016-01-03    False    False     NaT     NaT
1   1 2016-02-07     True    False  0 days     NaT
2   1 2016-02-18    False     True 11 days  0 days
3   2 2016-01-01    False     True     NaT  0 days
4   2 2016-01-04    False    False     NaT  3 days
5   2 2016-02-02     True    False  0 days 32 days
6   2 2016-02-04    False    False  2 days 34 days
7   2 2016-02-05    False     True  3 days  0 days
这是因为(使用event_2,因为它有两个不同的Trues,所以更有趣)首先,我们只选择“开始”时间:

然后我们按ID分组,并提前填写参考日期:

In [177]: df["date"].where(df["event_2"]).groupby(df["ID"]).ffill()
Out[177]: 
0          NaT
1          NaT
2   2016-02-18
3   2016-01-01
4   2016-01-01
5   2016-01-01
6   2016-01-01
7   2016-02-05
Name: date, dtype: datetime64[ns]
在这之后,我们只需要减去得到时间差。你可以用

df["time_1"] = df["time_1"].dt.days
df["time_2"] = df["time_2"].dt.days

如果您愿意,可以使用浮动而不是时间增量。

事件1与事件2有关系吗?是否应按ID进行计算?为什么存在空值(
-
)?它们的逻辑是什么?@Joost事件是独立的,计算是按照
ID
进行的。我要编辑这个问题。谢谢你的支持questions@RafaelC
-
的含义是
None
pandas
中对于
非日期时间的等价物。我问为什么会有空值?例如,为什么
time_1
的第一个值不是零,第二个值不是
2016-02-07
2016-01-03
之间的差值?逻辑是什么?事件1和事件2有什么关系吗?是否应按ID进行计算?为什么存在空值(
-
)?它们的逻辑是什么?@Joost事件是独立的,计算是按照
ID
进行的。我要编辑这个问题。谢谢你的支持questions@RafaelC
-
的含义是
None
pandas
中对于
非日期时间的等价物。我问为什么会有空值?例如,为什么
time_1
的第一个值不是零,第二个值不是
2016-02-07
2016-01-03
之间的差值?逻辑是什么?你能添加取消设置索引然后恢复它们的代码吗?你能添加取消设置索引然后恢复它们的代码吗?