验证列是否在数据框中逐行添加一天
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_datetime
将 Date_To
和 Date_From
列转换为 pandas 日期时间系列。
第 2 步:使用 np.arange
在 df
中创建一个临时列 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.eq
和 level=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 来自 OK
和 WARNING
的标量值
# 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
我有以下数据框作为示例(已按 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_datetime
将 Date_To
和 Date_From
列转换为 pandas 日期时间系列。
第 2 步:使用 np.arange
在 df
中创建一个临时列 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.eq
和 level=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 来自 OK
和 WARNING
的标量值
# 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