J'ai chargé un DataFrame à partir d'une table SQLServer. Cela ressemble à ceci:
>>> df.show()
+--------------------+----------+
| timestamp| Value |
+--------------------+----------+
|2015-12-02 00:10:...| 652.8|
|2015-12-02 00:20:...| 518.4|
|2015-12-02 00:30:...| 524.6|
|2015-12-02 00:40:...| 382.9|
|2015-12-02 00:50:...| 461.6|
|2015-12-02 01:00:...| 476.6|
|2015-12-02 01:10:...| 472.6|
|2015-12-02 01:20:...| 353.0|
|2015-12-02 01:30:...| 407.9|
|2015-12-02 01:40:...| 475.9|
|2015-12-02 01:50:...| 513.2|
|2015-12-02 02:00:...| 569.0|
|2015-12-02 02:10:...| 711.4|
|2015-12-02 02:20:...| 457.6|
|2015-12-02 02:30:...| 392.0|
|2015-12-02 02:40:...| 459.5|
|2015-12-02 02:50:...| 560.2|
|2015-12-02 03:00:...| 252.9|
|2015-12-02 03:10:...| 228.7|
|2015-12-02 03:20:...| 312.2|
+--------------------+----------+
Maintenant, je voudrais grouper (et additionner) les valeurs par heure (ou jour, ou mois ou ...), mais je n'ai pas vraiment la moindre idée de comment je peux faire ça.
Voilà comment je charge le DataFrame. J'ai le sentiment que ce n'est pas la bonne façon de le faire, cependant:
query = """
SELECT column1 AS timestamp, column2 AS value
FROM table
WHERE blahblah
"""
sc = SparkContext("local", 'test')
sqlctx = SQLContext(sc)
df = sqlctx.load(source="jdbc",
url="jdbc:sqlserver://<CONNECTION_DATA>",
dbtable="(%s) AS alias" % query)
Est-ce que c'est bon?
Depuis 1.5.0 Spark fournit un certain nombre de fonctions comme dayofmonth
, hour
, month
ou year
qui peuvent fonctionner sur les dates et les horodatages. Donc, si timestamp
est un TimestampType
tout ce dont vous avez besoin est une expression correcte. Par exemple:
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|
## +----+------------------+
Avant la version 1.5.0, votre meilleure option est d'utiliser HiveContext
et Hive UDF avec selectExpr
:
df.selectExpr("year(timestamp) AS year", "value").groupBy("year").sum()
## +----+---------+----------+
## |year|SUM(year)|SUM(value)|
## +----+---------+----------+
## |2015| 40300| 9183.0|
## +----+---------+----------+
ou SQL brut:
df.registerTempTable("df")
sqlContext.sql("""
SELECT MONTH(timestamp) AS month, SUM(value) AS values_sum
FROM df
GROUP BY MONTH(timestamp)""")
N'oubliez pas que l'agrégation est effectuée par Spark non poussé vers le bas vers la source externe. Habituellement, c'est un comportement souhaité mais il y a des situations où vous pouvez préférer effectuer l'agrégation en tant que sous-requête pour limiter le transfert de données .
En outre, vous pouvez utiliser date_format pour créer la période que vous souhaitez. Groupby jour spécifique:
from pyspark.sql import functions as F
df.select(F.date_format('timestamp','yyyy-MM-dd').alias('day')).groupby('day').count().show()
Grouper un mois spécifique (il suffit de changer le format):
df.select(F.date_format('timestamp','yyyy-MM').alias('month')).groupby('month').count().show()