验证列是否在数据框中逐行添加一天

Validate if column is adding a day row by row in a dataframe

我有以下数据框作为示例(已按 PERSON_NUMBER 订购):

                Date_From     Date_To PROPOSAL_REASON
PERSON_NUMBER                                        
3720081000     2008-01-04  2009-12-07           MEINC
3720081000     2018-07-01  2019-03-31           MEINC
3720081000     2019-04-01  2019-10-31           MEINC
3720081018     2018-07-01  2019-03-31           MEINC
3720081018     2019-04-01  2019-10-31           MEINC
3720081077     2018-07-01  2019-03-31           MEINC
3720081111     2019-04-01  2019-10-31           MEINC
3720081211     2018-07-01  2019-03-31           MEINC
3720081211     2019-06-01  2019-10-31           MEINC

我需要验证每个员工(每个员工可以有 1 个或多个记录)如果每一行,第一个记录 +1 天的 Date_To 应该是 Date_From第二条记录意味着创建记录的天数应该没有差距。

对于有这个差距的员工,我想过滤并将它们保存在另一个数据框中。

因此,例如,从给定的数据框中,我希望以下输出创建一个包含此信息的列(记录的第一行始终 OK):

                Date_From     Date_To     CHECK_CONDITION
PERSON_NUMBER                                        
3720081000     2008-01-04  2009-12-07           OK
3720081000     2018-07-01  2019-03-31           WARNING
3720081000     2019-04-01  2019-10-31           OK
3720081018     2018-07-01  2019-03-31           OK
3720081018     2019-04-01  2019-10-31           OK
3720081077     2018-07-01  2019-03-31           OK
3720081111     2019-04-01  2019-10-31           OK
3720081211     2018-07-01  2019-03-31           OK
3720081211     2019-06-01  2019-10-31           WARNING

因此,如您所见,记录 WARNING Date_From 值不是之前的 Date_To 值 + 1 天

你可以试试这个:

df['Date_From'] = pd.to_datetime(df['Date_From'])
df['Date_To'] = pd.to_datetime(df['Date_To'])
df['CHECK_CONDITION'] = (df['Date_From'] - df['Date_To'].shift()).dt.days != 1
print(df)

   PERSON_NUMBER  Date_From    Date_To PROPOSAL_REASON  CHECK_CONDITION
0     3720081000 2008-01-04 2009-12-07           MEINC             True
1     3720081000 2018-07-01 2019-03-31           MEINC             True
2     3720081000 2019-04-01 2019-10-31           MEINC            False
3     3720081018 2018-07-01 2019-03-31           MEINC             True
4     3720081018 2019-04-01 2019-10-31           MEINC            False
5     3720081077 2018-07-01 2019-03-31           MEINC             True
6     3720081111 2019-04-01 2019-10-31           MEINC            False
7     3720081211 2018-07-01 2019-03-31           MEINC             True
8     3720081211 2019-06-01 2019-10-31           MEINC             True

使用:

# STEP 1
df['Date_To'] = pd.to_datetime(df['Date_To'])
df['Date_From'] = pd.to_datetime(df['Date_From'])

# STEP 2
df['count'] = np.arange(df.shape[0])

# STEP 3
m1 = df['Date_From'].sub(df['Date_To'].shift()).dt.days.eq(1)

# STEP 4
m2 = df['count'].eq(df.groupby(level=0)['count'].transform('first'))

# STEP 5
df1 = df.assign(CHECK_CONDITION=np.where(m1 | m2, 'OK', 'WARNING')).drop('count', 1)

解释:

第 1 步:使用 pd.to_datetimeDate_ToDate_From 列转换为 pandas 日期时间系列。

第 2 步:使用 np.arangedf 中创建一个临时列 count 作为 datframe 中行的唯一计数器,这有助于跟踪边界条件这有助于区分排序后的数据框中的下一位员工和上一位员工。

# df
               Date_From    Date_To PROPOSAL_REASON  count
PERSON_NUMBER                                             
3720081000    2008-01-04 2009-12-07           MEINC      0
3720081000    2018-07-01 2019-03-31           MEINC      1
3720081000    2019-04-01 2019-10-31           MEINC      2
3720081018    2018-07-01 2019-03-31           MEINC      3
3720081018    2019-04-01 2019-10-31           MEINC      4
3720081077    2018-07-01 2019-03-31           MEINC      5
3720081111    2019-04-01 2019-10-31           MEINC      6
3720081211    2018-07-01 2019-03-31           MEINC      7
3720081211    2019-06-01 2019-10-31           MEINC      8

第 3 步:通过从移位的 "Date_To" 列中减去 "Date_From" 创建一个布尔掩码 m1,然后使用 Series.dt.days to get the number of days between the two columns then use Series.eq 创建一个布尔掩码,其中真值对应于总天数等于 1.

的条件
# m1
PERSON_NUMBER
3720081000    False
3720081000    False
3720081000     True
3720081018    False
3720081018     True
3720081077    False
3720081111     True
3720081211    False
3720081211    False
dtype: bool

第 4 步:使用 Series.eqlevel=0 上的 DataFrame.groupby 创建布尔掩码 m2,其中真实值对应于员工 ID 的边界条件。

# m2
PERSON_NUMBER
3720081000     True
3720081000    False
3720081000    False
3720081018     True
3720081018    False
3720081077     True
3720081111     True
3720081211     True
3720081211    False
Name: count, dtype: bool

第 5 步:根据条件 m1 | m2

,使用 np.where 到 select 来自 OKWARNING 的标量值
# df1 (RESULT)
               Date_From    Date_To PROPOSAL_REASON CHECK_CONDITION
PERSON_NUMBER                                                      
3720081000    2008-01-04 2009-12-07           MEINC              OK
3720081000    2018-07-01 2019-03-31           MEINC         WARNING
3720081000    2019-04-01 2019-10-31           MEINC              OK
3720081018    2018-07-01 2019-03-31           MEINC              OK
3720081018    2019-04-01 2019-10-31           MEINC              OK
3720081077    2018-07-01 2019-03-31           MEINC              OK
3720081111    2019-04-01 2019-10-31           MEINC              OK
3720081211    2018-07-01 2019-03-31           MEINC              OK
3720081211    2019-06-01 2019-10-31           MEINC         WARNING