我有以下DataFrame:
+----------+
| date|
+----------+
|2017-01-25|
|2017-01-21|
|2017-01-12|
+----------+
以下是DataFrame上方创建的代码:
import pyspark.sql.functions as f
rdd = sc.parallelize([("2017/11/25",), ("2017/12/21",), ("2017/09/12",)])
df = sqlContext.createDataFrame(rdd, ["date"]).withColumn("date", f.to_date(f.col("date"), "yyyy/MM/dd"))
df.show()
我想要一个新列,每行的第一个日期,只需将日期替换为" 01"在所有日期
+----------++----------+
| date| first_date|
+----------++----------+
|2017-11-25| 2017-11-01|
|2017-12-21| 2017-12-01|
|2017-09-12| 2017-09-01|
+----------+-----------+
PySpark.sql.function中有一个last_day函数,但是没有first_day函数。
我尝试使用date_sub来执行此操作但不起作用:我得到一个列而不是Iterable错误,因为date_sub的第二个参数不能是一个列而必须是一个整数。
f.date_sub(f.col('date'), f.dayofmonth(f.col('date')) - 1 )
答案 0 :(得分:10)
您可以使用trunc
:
df.withColumn("first_date", f.trunc("date", "month")).show()
+----------+----------+
| date|first_date|
+----------+----------+
|2017-11-25|2017-11-01|
|2017-12-21|2017-12-01|
|2017-09-12|2017-09-01|
+----------+----------+
答案 1 :(得分:0)
我认为这是语法错误,请你改变f.dayofmonth - > dayofmonth并尝试。表达看起来很好。
f.date_sub(f.col('Match_date'),dayofmonth(f.col('Match_date')) - 1 )
答案 2 :(得分:0)
你不能使用字符串操作并将最后2个字符转换为"01"
吗?
import pyspark.sql.functions as f
rdd = sc.parallelize([("2017/11/25",), ("2017/12/21",), ("2017/09/12",)])
df = sqlCtx.createDataFrame(rdd, ["date"])
df.withColumn(
'first_date',
f.udf(lambda x: x[0:8] + "01", StringType())(f.col('date'))).show()
输出:
+----------+----------+
| date|first_date|
+----------+----------+
|2017/11/25|2017/11/01|
|2017/12/21|2017/12/01|
|2017/09/12|2017/09/01|
+----------+----------+
答案 3 :(得分:0)
您可以使用提到的 trunc
函数(如 Alper)或使用 date_trunc
方法获取月初。 trunc
函数返回日期列,date_trunc
函数返回时间列。假设您有以下 DataFrame:
+----------+
| some_date|
+----------+
|2017-11-25|
|2017-12-21|
|2017-09-12|
| null|
+----------+
运行 trunc
和 date_trunc
函数:
datesDF\
.withColumn("beginning_of_month_date", trunc(col("some_date"), "month"))\
.withColumn("beginning_of_month_time", date_trunc("month" ,col("some_date")))\
.show()
观察结果:
+----------+-----------------------+-----------------------+
| some_date|beginning_of_month_date|beginning_of_month_time|
+----------+-----------------------+-----------------------+
|2017-11-25| 2017-11-01| 2017-11-01 00:00:00|
|2017-12-21| 2017-12-01| 2017-12-01 00:00:00|
|2017-09-12| 2017-09-01| 2017-09-01 00:00:00|
| null| null| null|
+----------+-----------------------+-----------------------+
打印模式以确认列类型:
root
|-- some_date: date (nullable = true)
|-- beginning_of_month_date: date (nullable = true)
|-- beginning_of_month_time: timestamp (nullable = true)
Scala 用户应使用 spark-daria 中定义的 beginningOfMonthDate
和 beginningOfMonthTime
函数。
PySpark 用户应使用 quinn 中定义的 beginning_of_month_date
和 beginning_of_month_time
函数。
请注意 trunc
函数是如何首先接受列参数,而 date_trunc
是其次接受列参数的。 trunc
方法命名不当 - 它是函数包的一部分,因此很容易误认为该函数用于字符串截断。令人惊讶的是,date_trunc
正在返回一个时间戳结果......听起来它应该返回一个日期结果。
只需确保使用描述性函数/UDF 名称包装这些函数,以便您的代码可读。有关详细信息,请参阅 here。