PySpark: фильтрация фрейма данных по полю даты в диапазоне, где дата-строка
мои фреймы данных содержат одно поле, которое является датой, и оно отображается в строковом формате, например
'2015-07-02T11:22:21.050Z'
мне нужно отфильтровать фрейм данных на дату, чтобы получить только записи за последнюю неделю. Итак, я пробовал подход карты, где я преобразовал строковые даты в объекты datetime с помощью strptime:
def map_to_datetime(row):
format_string = '%Y-%m-%dT%H:%M:%S.%fZ'
row.date = datetime.strptime(row.date, format_string)
df = df.map(map_to_datetime)
и тогда я бы применил фильтр как
df.filter(lambda row:
row.date >= (datetime.today() - timedelta(days=7)))
мне удается заставить отображение работать, но фильтр не работает с
TypeError: условие должно быть строкой или столбцом
есть ли способ использовать фильтрацию таким образом, который работает или я должен изменить подход и как?
2 ответов
вы можете решить эту проблему без использования кода Python рабочей стороны и переключения на RDDs. Прежде всего, поскольку вы используете строку ISO 8601, ваши данные могут быть непосредственно отлиты на дату или метку времени:
from pyspark.sql.functions import col
df = sc.parallelize([
('2015-07-02T11:22:21.050Z', ),
('2016-03-20T21:00:00.000Z', )
]).toDF(("d_str", ))
df_casted = df.select("*",
col("d_str").cast("date").alias("dt"),
col("d_str").cast("timestamp").alias("ts"))
это сэкономит один раунд между JVM и Python. Есть также несколько способов, которыми вы можете подойти ко второй части. Только дата:
from pyspark.sql.functions import current_date, datediff, unix_timestamp
df_casted.where(datediff(current_date(), col("dt")) < 7)
метки:
def days(i: int) -> int:
return 60 * 60 * 24 * i
df_casted.where(unix_timestamp() - col("ts").cast("long") < days(7))
вы также можете посмотреть current_timestamp
и date_sub
Примечание: I избегайте использования DataFrame.map
. Лучше использовать . Это сэкономит вам некоторую работу при переключении на 2.0+
Я понял, как решить мою проблему, используя SparkSQL API с датами, хранящимися в виде строк, и делая это:
last_week = (datetime.today() - timedelta(days=7)).strftime(format='%Y-%m-%d')
new_df = df.where(df.date >= last_week)