Python 一种快速、有效的方法来计算大熊猫行组之间的时间差?

Python 一种快速、有效的方法来计算大熊猫行组之间的时间差?,python,pandas,dataframe,Python,Pandas,Dataframe,假设我在一个数据框中有这个表,其中有几辆车的加油日期: +-------+-------------+ | carId | refill_date | +-------+-------------+ | 1 | 2020-03-01 | +-------+-------------+ | 1 | 2020-03-12 | +-------+-------------+ | 1 | 2020-04-04 | +-------+-------------+ |

假设我在一个数据框中有这个表,其中有几辆车的加油日期:

+-------+-------------+
| carId | refill_date |
+-------+-------------+
|     1 |  2020-03-01 |
+-------+-------------+
|     1 |  2020-03-12 |
+-------+-------------+
|     1 |  2020-04-04 |
+-------+-------------+
|     2 |  2020-03-07 |
+-------+-------------+
|     2 |  2020-03-26 |
+-------+-------------+
|     2 |  2020-04-01 |
+-------+-------------+
我想添加第三列,time_Passed,以及每次加注之间的持续时间

+-------+-------------+--------------+
| carId | refill_date | time_elapsed |
+-------+-------------+--------------+
|     1 |  2020-03-01 |              |
+-------+-------------+--------------+
|     1 |  2020-03-12 |           11 |
+-------+-------------+--------------+
|     1 |  2020-04-04 |           23 |
+-------+-------------+--------------+
|     2 |  2020-03-07 |              |
+-------+-------------+--------------+
|     2 |  2020-03-26 |           19 |
+-------+-------------+--------------+
|     2 |  2020-04-01 |            6 |
+-------+-------------+--------------+
下面是我的工作:

作为pd进口熊猫 df=pd.DataFrame 数据=[ { carId:1, 加注日期:2020-3-1 }, { carId:1, 加注日期:2020-3-12 }, { carId:1, 加注日期:2020-4-4 }, { carId:2, 加注日期:2020-3-7 }, { carId:2, 加注日期:2020-3-26 }, { carId:2, 加注日期:2020-4-1 } ] df=pd.DataFramedata df['refill_date']=pd.to_datetimedf['refill_date'] 对于df['carId']中的c。唯一性: df.loc[df['carId']==c,'经过的时间']=df.loc[df['carId']==c, “重新加注日期”].diff 它返回预期结果:

+---+-------+-------------+--------------+
|   | carId | refill_date | time_elapsed |
+---+-------+-------------+--------------+
| 0 |     1 |  2020-03-01 |          NaT |
+---+-------+-------------+--------------+
| 1 |     1 |  2020-03-12 |      11 days |
+---+-------+-------------+--------------+
| 2 |     1 |  2020-04-04 |      23 days |
+---+-------+-------------+--------------+
| 3 |     2 |  2020-03-07 |          NaT |
+---+-------+-------------+--------------+
| 4 |     2 |  2020-03-26 |      19 days |
+---+-------+-------------+--------------+
| 5 |     2 |  2020-04-01 |       6 days |
+---+-------+-------------+--------------+
所以,看起来一切正常,但这里有一个陷阱:在我的现实生活实例中,我的数据帧包含350万行,处理需要很长时间,尽管这是一个完全数字化的内存计算,只有1711个组可以循环

有没有其他更快捷的方法


谢谢

通过使用重新加注日期并从中减去来获取经过的时间

(
    df.assign(
        refill_date=pd.to_datetime(df.refill_date),
        time_shift=lambda x: x.groupby("carId").refill_date.shift(),
        time_elapsed=lambda x: x.time_shift.sub(x.refill_date).abs(),
    )
)

使用的其他答案更好,因为这更简洁,而且我相信更快。

通过使用并减去重新加注日期来获取所用的时间

(
    df.assign(
        refill_date=pd.to_datetime(df.refill_date),
        time_shift=lambda x: x.groupby("carId").refill_date.shift(),
        time_elapsed=lambda x: x.time_shift.sub(x.refill_date).abs(),
    )
)
使用的其他答案更好,因为这更简洁,而且我相信更快。

您只需要使用。groupby:

输出:

  refill_date
0         NaT
1     11 days
2     23 days
3         NaT
4     19 days
5      6 days
您只需使用。groupby:

输出:

  refill_date
0         NaT
1     11 days
2     23 days
3         NaT
4     19 days
5      6 days

在df.groupby上使用本机pandas方法应能显著提高本机python循环的性能:

df['time_appeased']=df.groupby'carId'['refill_date'].diff 这是我笔记本电脑上的一个小基准,YMMV。。。使用100辆车,每辆车使用31天, 性能提升近10倍:

作为pd进口熊猫 导入时间信息 数据=[{carId:carId,重新加注日期:2020-3-+strday}范围1100的carId,范围1,32的一天] df=pd.DataFramedata df['refill_date']=pd.to_datetimedf['refill_date'] def原始方法: 对于df['carId']中的c。唯一性: df.loc[df['carId']==c,'经过的时间']=df.loc[df['carId']==c, “重新加注日期”].diff def使用_groupby: df['time_appeased']=df.groupby'carId'['refill_date'].diff time1=timeit.timeit‘原始_方法’,globals=globals,number=100 time2=timeit.timeit'using_groupby',globals=globals,number=100 打印时间1 打印时间2 打印时间1/2 输出:

16.6183732
1.7910263000000022
9.278687420726307

在df.groupby上使用本机pandas方法应能显著提高本机python循环的性能:

df['time_appeased']=df.groupby'carId'['refill_date'].diff 这是我笔记本电脑上的一个小基准,YMMV。。。使用100辆车,每辆车使用31天, 性能提升近10倍:

作为pd进口熊猫 导入时间信息 数据=[{carId:carId,重新加注日期:2020-3-+strday}范围1100的carId,范围1,32的一天] df=pd.DataFramedata df['refill_date']=pd.to_datetimedf['refill_date'] def原始方法: 对于df['carId']中的c。唯一性: df.loc[df['carId']==c,'经过的时间']=df.loc[df['carId']==c, “重新加注日期”].diff def使用_groupby: df['time_appeased']=df.groupby'carId'['refill_date'].diff time1=timeit.timeit‘原始_方法’,globals=globals,number=100 time2=timeit.timeit'using_groupby',globals=globals,number=100 打印时间1 打印时间2 打印时间1/2 输出:

16.6183732
1.7910263000000022
9.278687420726307

还可以考虑浮点列的链接。dt.Day.使用GROMPBY的问题是,我没有得到预期的输出。我不想做一个聚合,而是在原始列中添加一个新列。如果我运行df.groupby'carId'.diff.reset_index,我将不再具有映射时差的carId。我可以假设所有行的顺序都相同,并且我可以将表并排连接到pd.concat[df,df.groupby'carId.diff],axis=1吗?看起来确实存在匹配。我没想到groupby会这么做,因为我不想收集数据,但我现在知道它不仅仅是聚合-还可以考虑浮点列的链接。dt.Day.使用GROMPBY的问题是,我没有得到预期的输出。我不想做一个聚合,而是在原始列中添加一个新列。如果我运行df.groupby'carId'.diff.reset_index,我将不再具有映射时差的carId。我可以假设所有行的顺序都相同,并且我可以将表并排连接到pd.concat[df,df.groupby'carId.diff],axis=1吗?看起来确实存在匹配。我不认为groupby会这么做,因为我不想收集数据,但现在我知道它做了很多事情 比聚合更重要!:-