Solución:
Desde 1.5.0 Spark proporciona una serie de funciones como dayofmonth
, hour
, month
o year
que puede operar en fechas y marcas de tiempo. Así que si timestamp
es un TimestampType
todo lo que necesitas es una expresión correcta. Por ejemplo:
from pyspark.sql.functions import hour, mean
(df
.groupBy(hour("timestamp").alias("hour"))
.agg(mean("value").alias("mean"))
.show())
## +----+------------------+
## |hour| mean|
## +----+------------------+
## | 0|508.05999999999995|
## | 1| 449.8666666666666|
## | 2| 524.9499999999999|
## | 3|264.59999999999997|
## +----+------------------+
Pre-1.5.0, su mejor opción es usar HiveContext
y UDF de Hive con selectExpr
:
df.selectExpr("year(timestamp) AS year", "value").groupBy("year").sum()
## +----+---------+----------+
## |year|SUM(year)|SUM(value)|
## +----+---------+----------+
## |2015| 40300| 9183.0|
## +----+---------+----------+
o SQL sin formato:
df.registerTempTable("df")
sqlContext.sql("""
SELECT MONTH(timestamp) AS month, SUM(value) AS values_sum
FROM df
GROUP BY MONTH(timestamp)""")
Solo recuerde que Spark realiza la agregación y no se envía a la fuente externa. Por lo general, es un comportamiento deseado, pero hay situaciones en las que puede preferir realizar la agregación como una subconsulta para limitar la transferencia de datos.
Además, puede usar date_format para crear cualquier período de tiempo que desee. Grupo por día específico:
from pyspark.sql import functions as F
df.select(F.date_format('timestamp','yyyy-MM-dd').alias('day')).groupby('day').count().show()
Agrupar por mes específico (solo cambie el formato):
df.select(F.date_format('timestamp','yyyy-MM').alias('month')).groupby('month').count().show()