Проверить, добавляет ли столбец день за строкой в ​​фрейм данных - PullRequest
1 голос
/ 18 июня 2020

В качестве примера у меня есть следующий фрейм данных (уже заказан на 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 или несколько записей), если каждый В строке Date_To из первой записи +1 день должно быть 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 день

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Используйте:

# 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 datetime series.

ШАГ 2: Используйте np.arange для создания временного столбца count в df, который действует как уникальный счетчик для строк в кадре данных, это помогает отслеживать граничные условия, которые могут поможет отличить следующего сотрудника от предыдущего в отсортированном фрейме данных.

# 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: Создайте логическую маску m1, вычтя «Date_From» из смещенного столбца «Date_To», затем используйте Series.dt.days, чтобы получить количество дней между двумя столбцами, затем используйте 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: Создайте логическую маску m2, используя Series.eq и DataFrame.groupby на level=0, где истинные значения соответствуют граничному условию идентификатора сотрудника .

# 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: Используйте np.where для выбора скалярных значений из OK и WARNING на основе условий m1 | m2:

# 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
0 голосов
/ 18 июня 2020

Вы можете попробовать это:

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
...