我正在尝试使用PySpark数据框中的多个列进行一些中等复杂的日期算术。基本上,我有一个名为number
的列,表示我需要过滤的created_at
时间戳之后的周数。在PostgreSQL中你可以乘以interval based on the value in a column,但我似乎无法使用SQL API或Python API在PySpark中弄清楚如何做到这一点。这里的任何帮助将非常感谢!
import datetime
from pyspark.sql import SQLContext
from pyspark.sql import Row
from pyspark import SparkContext
sc = SparkContext()
sqlContext = SQLContext(sc)
start_date = datetime.date(2020,1,1)
my_df = sc.parallelize([
Row(id=1, created_at=datetime.datetime(2020, 1, 1), number=1, metric=10),
Row(id=1, created_at=datetime.datetime(2020, 1, 1), number=2, metric=10),
Row(id=1, created_at=datetime.datetime(2020, 1, 1), number=3, metric=10),
Row(id=2, created_at=datetime.datetime(2020, 1, 15), number=1, metric=20),
Row(id=2, created_at=datetime.datetime(2020, 1, 15), number=2, metric=20),
Row(id=3, created_at=datetime.datetime(2020, 7, 1), number=7, metric=30),
Row(id=3, created_at=datetime.datetime(2020, 7, 1), number=8, metric=30),
Row(id=3, created_at=datetime.datetime(2020, 7, 1), number=9, metric=30),
Row(id=3, created_at=datetime.datetime(2020, 7, 1), number=10, metric=30),
]).toDF()
# This doesn't work!
new_df = my_df.where("created_at + interval 7 days * number > '" + start_date.strftime("%Y-%m-%d") +"'")
# Neither does this!
new_df = my_df.filter(my_df.created_at + datetime.timedelta(days=my_df.number * 7)).date() > start_date.date()
有可能solution here需要将日期转换为字符串,使用python中的datetime
库将字符串转换为datetime
对象,然后执行操作,但这似乎很疯狂。
答案 0 :(得分:6)
好吧,我使用expr
和内置date_add
函数找到了前进的方法。
from pyspark.sql.functions import expr, date_add
new_df = my_df.withColumn('test', expr('date_add(created_at, number*7)'))
filtered = new_df.filter(new_df.test > start_date)
filtered.show()
如果有其他人愿意添加,我会非常喜欢透露一般情况下如何/为何如此有效的方法!