Spark 数据帧时间戳类型 - 如何从字段中获取年、月、日值



我有 Spark 数据帧,上面有 take(5) 行,如下所示:

[Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=1, value=638.55),
 Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=2, value=638.55),
 Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=3, value=638.55),
 Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=4, value=638.55),
 Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=5, value=638.55)]

它的架构定义为:

elevDF.printSchema()
root
 |-- date: timestamp (nullable = true)
 |-- hour: long (nullable = true)
 |-- value: double (nullable = true)

如何从"日期"字段中获取年、月、日值?

从 Spark 1.5 开始,您可以使用许多日期处理函数:

  • pyspark.sql.functions.year
  • pyspark.sql.functions.month
  • pyspark.sql.functions.dayofmonth
  • pyspark.sql.functions.dayofweek
  • pyspark.sql.functions.dayofyear
  • pyspark.sql.functions.weekofyear
import datetime
from pyspark.sql.functions import year, month, dayofmonth
elevDF = sc.parallelize([
    (datetime.datetime(1984, 1, 1, 0, 0), 1, 638.55),
    (datetime.datetime(1984, 1, 1, 0, 0), 2, 638.55),
    (datetime.datetime(1984, 1, 1, 0, 0), 3, 638.55),
    (datetime.datetime(1984, 1, 1, 0, 0), 4, 638.55),
    (datetime.datetime(1984, 1, 1, 0, 0), 5, 638.55)
]).toDF(["date", "hour", "value"])
elevDF.select(
    year("date").alias('year'), 
    month("date").alias('month'), 
    dayofmonth("date").alias('day')
).show()
# +----+-----+---+
# |year|month|day|
# +----+-----+---+
# |1984|    1|  1|
# |1984|    1|  1|
# |1984|    1|  1|
# |1984|    1|  1|
# |1984|    1|  1|
# +----+-----+---+
<小时 />

您可以像使用任何其他RDD一样使用简单的map

elevDF = sqlContext.createDataFrame(sc.parallelize([
    Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=1, value=638.55),
    Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=2, value=638.55),
    Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=3, value=638.55),
    Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=4, value=638.55),
    Row(date=datetime.datetime(1984, 1, 1, 0, 0), hour=5, value=638.55)]))
(elevDF
    .map(lambda (date, hour, value): (date.year, date.month, date.day))
    .collect())

结果是:

[(1984, 1, 1), (1984, 1, 1), (1984, 1, 1), (1984, 1, 1), (1984, 1, 1)]

顺便说一句,无论如何datetime.datetime存储小时,因此将其分开保存似乎是浪费内存。

你可以在pyspark.sql.functions中使用函数:像yearmonthetc这样的函数。

有关可用函数的详细信息,请参阅 PySpark 的官方 DataFrame 文档。

from pyspark.sql.functions import *
newdf = elevDF.select(year(elevDF.date).alias('dt_year'), month(elevDF.date).alias('dt_month'), dayofmonth(elevDF.date).alias('dt_day'), dayofyear(elevDF.date).alias('dt_dayofy'), hour(elevDF.date).alias('dt_hour'), minute(elevDF.date).alias('dt_min'), weekofyear(elevDF.date).alias('dt_week_no'), unix_timestamp(elevDF.date).alias('dt_int'))
newdf.show()

+-------+--------+------+---------+-------+------+----------+----------+
|dt_year|dt_month|dt_day|dt_dayofy|dt_hour|dt_min|dt_week_no|    dt_int|
+-------+--------+------+---------+-------+------+----------+----------+
|   2015|       9|     6|      249|      0|     0|        36|1441497601|
|   2015|       9|     6|      249|      0|     0|        36|1441497601|
|   2015|       9|     6|      249|      0|     0|        36|1441497603|
|   2015|       9|     6|      249|      0|     1|        36|1441497694|
|   2015|       9|     6|      249|      0|    20|        36|1441498808|
|   2015|       9|     6|      249|      0|    20|        36|1441498811|
|   2015|       9|     6|      249|      0|    20|        36|1441498815|

实际上,我们真的不需要导入任何 python 库。我们可以使用简单的SQL来分隔年,月,日。请参阅以下示例,

+----------+
|       _c0|
+----------+
|1872-11-30|
|1873-03-08|
|1874-03-07|
|1875-03-06|
|1876-03-04|
|1876-03-25|
|1877-03-03|
|1877-03-05|
|1878-03-02|
|1878-03-23|
|1879-01-18|

我的数据框中有一个日期列,其中包含日期、月份和年份,并假设我只想从该列中提取年份。

df.createOrReplaceTempView("res")
sqlDF = spark.sql("SELECT EXTRACT(year from `_c0`) FROM res ")

在这里,我创建一个临时视图并使用这一行存储年份值,输出将是,

+-----------------------+
|year(CAST(_c0 AS DATE))|
+-----------------------+
|                   1872|
|                   1873|
|                   1874|
|                   1875|
|                   1876|
|                   1876|
|                   1877|
|                   1877|
|                   1878|
|                   1878|
|                   1879|
|                   1879|
|                   1879|

最新更新