Как вычесть столбец дней из столбца дат в Pyspark?
учитывая следующий PySpark DataFrame
df = sqlContext.createDataFrame([('2015-01-15', 10),
('2015-02-15', 5)],
('date_col', 'days_col'))
как можно вычесть столбец дней из столбца даты? В этом примере результирующий столбец должен быть ['2015-01-05', '2015-02-10']
.
Я посмотрел на pyspark.sql.functions.date_sub()
, но для этого требуется столбец даты и один день, т. е. date_sub(df['date_col'], 10)
. В идеале, я бы предпочел сделать date_sub(df['date_col'], df['days_col'])
.
Я также попытался создать UDF:
from datetime import timedelta
def subtract_date(start_date, days_to_subtract):
return start_date - timedelta(days_to_subtract)
subtract_date_udf = udf(subtract_date, DateType())
df.withColumn('subtracted_dates', subtract_date_udf(df['date_col'], df['days_col'])
это технически работает, но я читал, что шаг между Spark и Python может вызвать проблемы производительности для больших наборов данных. Я могу придерживаться этого решения сейчас (не нужно преждевременно оптимизировать), но моя интуиция говорит, что должен быть способ сделать эту простую вещь без использования Python UDF.
4 ответов
я смог решить эту проблему с помощью selectExpr
.
df.selectExpr('date_sub(date_col, day_col) as subtracted_dates')
если вы хотите добавить столбец к исходному DF, просто добавьте *
выражение
df.selectExpr('*', 'date_sub(date_col, day_col) as subtracted_dates')
не самое элегантное решение, но если вы не хотите взломать SQL-выражения в Scala (не то, что это должно быть сложно, но они являются частными для sql
) что-то вроде этого должно сделать трюк:
from pyspark.sql import Column
def date_sub_(c1: Column, c2: Column) -> Column:
return ((c1.cast("timestamp").cast("long") - 60 * 60 * 24 * c2)
.cast("timestamp").cast("date"))
Для Python 2.х просто напишите аннотации типа.
С помощью withColumn функции, мы можем сделать date_sub функции
>>> df.withColumn('substracted_dates',date_sub('date_col','day_col'))
немного другой формат, но тоже работает:
df.registerTempTable("dfTbl")
newdf = spark.sql("""
SELECT *, date_sub(d.date_col, d.day_col) AS DateSub
FROM dfTbl d
""")