从 pandas 多索引数据透视表中的时间序列计算值

Calculating values from time series in pandas multi-indexed pivot tables

我在 pandas 中有一个数据框,它存储一个人的 ID、交互质量和交互日期。一个人可以在多个日期进行多次交互,因此为了帮助可视化和绘制它,我将其转换为一个枢轴 table 首先按 Id 然后按日期分组以分析随时间变化的模式。

例如

import pandas as pd
df = pd.DataFrame({'Id':['A4G8','A4G8','A4G8','P9N3','P9N3','P9N3','P9N3','C7R5','L4U7'],
                   'Date':['2016-1-1','2016-1-15','2016-1-30','2017-2-12','2017-2-28','2017-3-10','2019-1-1','2018-6-1','2019-8-6'],
                   'Quality':[2,3,6,1,5,10,10,2,2]})
pt = df.pivot_table(values='Quality', index=['Id','Date'])
print(pt)

导致这个:

Id Date Quality
A4G8 2016-1-1 2
2016-1-15 4
2016-1-30 6
P9N3 2017-2-12 1
2017-2-28 5
2017-3-10 10
2019-1-1 10
C7R5 2018-6-1 2
L4U7 2019-8-6 2

不过,我也想...

  1. 测量每个 Id 的每次交互从第一次交互开始的时间
  2. 测量与上一次使用相同 Id 的交互的时间

所以我会得到一个 table 类似于下面的

Id Date Quality Time From First Time To Prev
A4G8 2016-1-1 2 0 days NA days
2016-1-15 4 14 days 14 days
2016-1-30 6 29 days 14 days
P9N3 2017-2-12 1 0 days NA days
2017-2-28 5 15 days 15 days
2017-3-10 10 24 days 9 days

Id列是字符串类型,我把date列转成datetime,Quality列转成整数。

该列相当大(>10,000 个唯一 ID),因此出于性能原因,我尽量避免使用 for 循环。我猜解决方案是以某种方式使用 pd.eval 但我不知道如何正确应用它。

抱歉,我是一个 python、pandas、& stack overflow) 菜鸟,我还没有在任何地方找到答案,所以即使是一些关于在哪里寻找的指示也会很棒 :- ). 非常感谢

Dates 转换为日期时间,然后将每组的最小日期时间减去 GroupBy.transformb subtracted by column Date and for second new column use DataFrameGroupBy.diff:

df['Date'] = pd.to_datetime(df['Date'])
   
df['Time From First'] = df['Date'].sub(df.groupby('Id')['Date'].transform('min'))
df['Time To Prev'] = df.groupby('Id')['Date'].diff()
print (df)
     Id       Date  Quality Time From First Time To Prev
0  A4G8 2016-01-01        2          0 days          NaT
1  A4G8 2016-01-15        3         14 days      14 days
2  A4G8 2016-01-30        6         29 days      15 days
3  P9N3 2017-02-12        1          0 days          NaT
4  P9N3 2017-02-28        5         16 days      16 days
5  P9N3 2017-03-10       10         26 days      10 days
6  P9N3 2019-01-01       10        688 days     662 days
7  C7R5 2018-06-01        2          0 days          NaT
8  L4U7 2019-08-06        2          0 days          NaT
df["Date"] = pd.to_datetime(df.Date)
df = df.merge(
    df.groupby(["Id"]).Date.first(),
    on="Id",
    how="left",
    suffixes=["", "_first"]
)
df["Time From First"] = df.Date-df.Date_first
df['Time To Prev'] = df.groupby('Id').Date.diff()
df.set_index(["Id", "Date"], inplace=True)
df

输出: