python - 计算连续时间段的天数(Python,日期时间)

标签 python pandas datetime

我想计算连续期间的天数。

在下面的 df 中,我有四列:

  • id;代表一个人。
  • 期间;一个数字,其中最低的是第一个周期,最高的是最后一个周期。
  • in_date;经期开始的日期。
  • 过时;期间结束的日期。

我想构建一个执行以下操作的通用函数:

  • 计算连续周期的天数。如果两个周期之间的天数小于 90,则认为它们是连续的。

  • 如果某个 ID 的最后一个经期的 out_date 是 2013 年,我只想计算天数。如果最后一个经期的“out_date”是 2014 年或 2012 年,我想忽略该 ID。

  • 我想在结果变量中包含周期之间的天数。

我的问题是,由于我对 Python 相当陌生,我无法想出一个好主意如何计算周期之间的天数并对连续周期进行分类。任何帮助将不胜感激。

import pandas as pd
import numpy as np
import datetime

data = {'id':[1, 1, 1, 2, 2, 2, 2, 3, 3, 3],
        'period':[1, 2, 3, 1, 3, 5, 6, 2, 3, 4],
       'in_date': ['2011-02-15','2011-11-10','2012-10-13',
                   '2010-04-03','2012-02-17','2012-08-15','2014-01-04','2010-06-01','2012-03-29','2012-09-12'],
       'out_date': ['2011-05-21','2012-10-11','2013-10-25',
                    '2012-02-16','2012-02-19','2013-11-23','2014-12-18','2011-08-21','2012-09-11','2013-01-10']}
df = pd.DataFrame(data)

df['in_date'] = pd.to_datetime(df['in_date'])
df['out_date'] = pd.to_datetime(df['out_date'])
df['n_days'] = df['out_date'] - df['in_date']

预期输出:

enter image description here

最佳答案

首先,将n_days转换为数值并确保df已排序:

df['n_days'] = (df['out_date'] - df['in_date']).dt.days
df = df.sort_values(['id','period'])

添加一列计算周期之间的天数:

df['days_since_last'] = (df['in_date'] - df['out_date'].shift(1)).dt.days

...并确保这些值不会在不同的 id 值之间交叉:

id_changed = (df['id'].shift(1) != df['id'])
df.loc[id_changed, 'days_since_last'] = np.nan

定义一个条件来记录间隔天数太长的情况:

days_cut = (df['days_since_last'] >= 90)

获取数据帧的子集,其中它是新的id或有效的连续运行天数。为每个有效运行分配一个唯一的“run”值(稍后用于分组):

tmp = df[days_cut | id_changed ].copy()
tmp['run'] = range(len(tmp))

将其合并回主数据帧并向前填充run,以便显示连续周期的有效运行位置:

df = pd.merge(df, tmp[['id','period','run']], on=['id','period'], how='left')
df['run'] = df['run'].fillna(method='ffill')

这就是当时的样子。您可以看到,对于每个 id ,都有连续的 run 值:

print(df)
   id  period    in_date   out_date  n_days  days_since_last  run
0   1       1 2011-02-15 2011-05-21      95              NaN  0.0
1   1       2 2011-11-10 2012-10-11     336            173.0  1.0
2   1       3 2012-10-13 2013-10-25     377              2.0  1.0
3   2       1 2010-04-03 2012-02-16     684              NaN  2.0
4   2       3 2012-02-17 2012-02-19       2              1.0  2.0
5   2       5 2012-08-15 2013-11-23     465            178.0  3.0
6   2       6 2014-01-04 2014-12-18     348             42.0  3.0
7   3       2 2010-06-01 2011-08-21     446              NaN  4.0
8   3       3 2012-03-29 2012-09-11     166            221.0  5.0
9   3       4 2012-09-12 2013-01-10     120              1.0  5.0

通过对 n_days 列求和来提取每次运行的连续天数。 .agg 还跟踪运行中的最大日期,因此我们只能保留 2013 年结束的运行:

consecutive_days = df.groupby(['id','run']).agg( {'n_days' : np.sum, 'out_date' : np.max } )
consecutive_days = consecutive_days[(consecutive_days['out_date'].dt.year == 2013)]

consecutive_days = consecutive_days.drop(columns=['out_date']).rename(columns={'n_days' : 'consecutive_days'})

最后,将其合并回原始数据框并删除多余的列:

df = pd.merge(df, consecutive_days, on='id', how='left')
df = df.drop(columns=['days_since_last','run'])

print(df)
   id  period    in_date   out_date  n_days  consecutive_days
0   1       1 2011-02-15 2011-05-21      95             713.0
1   1       2 2011-11-10 2012-10-11     336             713.0
2   1       3 2012-10-13 2013-10-25     377             713.0
3   2       1 2010-04-03 2012-02-16     684               NaN
4   2       3 2012-02-17 2012-02-19       2               NaN
5   2       5 2012-08-15 2013-11-23     465               NaN
6   2       6 2014-01-04 2014-12-18     348               NaN
7   3       2 2010-06-01 2011-08-21     446             286.0
8   3       3 2012-03-29 2012-09-11     166             286.0
9   3       4 2012-09-12 2013-01-10     120             286.0

关于python - 计算连续时间段的天数(Python,日期时间),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66030368/

相关文章:

python - 如何将自定义模板标签传递给 Jinja2 Template 类?

Python:多处理池中的产量

python - 将 Scrapy 作为脚本运行时禁用日志

python - 获取 pandas 中包含特定值的列名

python - Pandas 情节时间序列 ['numpy.ndarray' 对象没有属性 'find']

java - 如何以天为单位显示毫秒数 :hours:min:seconds

python - Django Rest Framework 自定义序列化器方法

python - 删除满足列值条件的 pandas 数据帧的初始行,同时保持列中的序列值不变

java - 当前日期和时间 ("Wall"任何时区的日期和时间

c# - 如何在周末在 C# 中分配唯一的员工