Проверка, находится ли какая-либо дата в списке дат Python между двумя столбцами даты - PullRequest
2 голосов
/ 11 июля 2019

У меня есть датафрейм с двумя столбцами.Одним из них является START_DATE, а другим - END_DATE.У меня также есть список дат Python.Мне нужен третий столбец в кадре данных, который указывает, попадает ли какая-либо из дат в моем списке python между START_DATE и END_DATE в кадре данных для каждой конкретной строки.Если в списке дат есть дата между START_DATE и END_DATE, в третьем столбце должно отображаться значение true.

dates_list = ['2019-01-06', '2019-04-08']

START_DATE|END_DATE|
____________________
2019-01-01|2019-01-12
2019-01-03|2019-01-05
2019-04-03|2019-04-09

Мне нужен третий столбец, показывающий

TRUE
FALSE
TRUE

Было бы здоровоиметь в pyspark, но панды тоже работают.

Ответы [ 4 ]

1 голос
/ 11 июля 2019

Если вы пометили pyspark , вы, вероятно, можете попробовать pyspark.sql.DataFrame.join :

Настройка

from pyspark.sql import functions as F

>>> df.show()
+-------------------+-------------------+
|         START_DATE|           END_DATE|
+-------------------+-------------------+
|2019-01-01 00:00:00|2019-01-12 00:00:00|
|2019-01-03 00:00:00|2019-01-05 00:00:00|
|2019-04-03 00:00:00|2019-04-09 00:00:00|
+-------------------+-------------------+

>>> df.printSchema()
root
 |-- START_DATE: timestamp (nullable = true)
 |-- END_DATE: timestamp (nullable = true)

# Convert List of Dates into a spark dataframe
dates_list = ['2019-01-06', '2019-04-08']
df_dates = spark.createDataFrame([(d,) for d in dates_list], ['date'])
df_dates = df_dates.withColumn('date', F.to_timestamp('date'))

>>> df_dates.show()
+-------------------+
|               date|
+-------------------+
|2019-01-06 00:00:00|
|2019-04-08 00:00:00|
+-------------------+

Присоединяйтесь (left_semi, left_anti), а затем Union

Используйте left_semi Join, чтобы получить все совпадающие строки, и left_anti JOIN, чтобы получить все несопоставленные строки, пометьте ряды, а затем объедините результаты

df_new = df.join(df_dates,
            (df_dates.date <= df.END_DATE) & (df_dates.date >= df.START_DATE)
          , how='left_semi'
    ).withColumn('Flag', F.lit(True)
).union(
         df.join(df_dates,
            (df_dates.date <= df.END_DATE) & (df_dates.date >= df.START_DATE)
          , how='left_anti'
    ).withColumn('Flag', F.lit(False))
)

>>> df_new.show()
+-------------------+-------------------+-----+
|         START_DATE|           END_DATE| Flag|
+-------------------+-------------------+-----+
|2019-01-01 00:00:00|2019-01-12 00:00:00| true|
|2019-04-03 00:00:00|2019-04-09 00:00:00| true|
|2019-01-03 00:00:00|2019-01-05 00:00:00|false|
+-------------------+-------------------+-----+
1 голос
/ 11 июля 2019

Это можно сделать с помощью pd.IntervalIndex. Давайте начнем с преобразования всех дат в datetime:

from datetime import datetime
df = df.apply(pd.to_datetime)
dates = [datetime.strptime(x, '%Y-%m-%d') for x in dates_list]

Теперь давайте создадим pd.IntervalIndex, используя его метод from_arrays, и проверим, какие интервалы содержат any дату из списка, используя понимание списка:

ix = pd.IntervalIndex.from_arrays(df['START_DATE'],df['END_DATE'],closed='both')
[any(date in i for date in dates) for i in ix]
# [True, False, True]
1 голос
/ 11 июля 2019

попробуйте использовать pd.date_range и методы пересечения набора для проверки даты существуют или нет

df = pd.DataFrame(data={"start_date":["2019-01-01","2019-01-03","2019-04-03"],
                       "end_date":["2019-01-12","2019-01-05","2019-04-09"]})
dates_list = ['2019-01-06', '2019-04-08']
def creating_dates(row,date_list):
    dates = list(pd.date_range(start=row['start_date'], end=row['end_date']).astype(str))
    res = set(dates).intersection(set(date_list))
    if res:
        return True
    return False
df['check_exist'] = df.apply(lambda x:creating_dates(x,dates_list),axis=1)

   start_date   end_date    check_exist
0   2019-01-01  2019-01-12  True
1   2019-01-03  2019-01-05  False
2   2019-04-03  2019-04-09  True
0 голосов
/ 11 июля 2019

Я все еще относительно новичок в Python, но подумал, что мне пора :)

надеюсь, это поможет!

Код

import pandas as pd
import numpy as np
from datetime import datetime

dict = {'START_DATE':['2019-01-01','2019-01-03','2019-04-03'],
        'END_DATE': ['2019-01-12','2019-01-05','2019-04-09'],
        'RESULT':['FALSE','FALSE','FALSE']}


dates_list = ['2019-01-06', '2019-04-08']

df = pd.DataFrame(dict)

print('BEFORE')
print(df)


for row in df.itertuples():

    start_date = datetime.fromisoformat(df.at[row.Index, 'START_DATE'])
    end_date = datetime.fromisoformat(df.at[row.Index, 'END_DATE'])     
    result = 'false'

    for datestr in dates_list:
        date = datetime.fromisoformat(datestr)

        if start_date <= date <= end_date:
            result = 'TRUE'
            df.at[row.Index, 'RESULT'] = result


print('AFTER')
print(df)

Даст вам

Вывод

BEFORE
   START_DATE    END_DATE RESULT
0  2019-01-01  2019-01-12  FALSE
1  2019-01-03  2019-01-05  FALSE
2  2019-04-03  2019-04-09  FALSE
AFTER
   START_DATE    END_DATE RESULT
0  2019-01-01  2019-01-12   TRUE
1  2019-01-03  2019-01-05  FALSE
2  2019-04-03  2019-04-09   TRUE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...