【问题标题】:Group spark dataframe by date按日期分组火花数据框
【发布时间】:2016-01-22 11:48:53
【问题描述】:

我已经从 SQLServer 表中加载了一个 DataFrame。它看起来像这样:

>>> 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|
+--------------------+----------+

现在我想按小时(或天、月或...)对值进行分组(和求和),但我真的不知道该怎么做。

这就是我加载 DataFrame 的方式。不过,我觉得这不是正确的做法:

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)

还好吗?

【问题讨论】:

    标签: python apache-spark pyspark apache-spark-sql


    【解决方案1】:

    从 1.5.0 开始,Spark 提供了许多函数,如 dayofmonthhourmonthyear,它们可以对日期和时间戳进行操作。因此,如果timestampTimestampType,您所需要的只是一个正确的表达式。例如:

    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|
    ## +----+------------------+
    

    在 1.5.0 之前,您最好的选择是将 HiveContext 和 Hive UDF 与 selectExpr 一起使用:

    df.selectExpr("year(timestamp) AS year", "value").groupBy("year").sum()
    
    ## +----+---------+----------+   
    ## |year|SUM(year)|SUM(value)|
    ## +----+---------+----------+
    ## |2015|    40300|    9183.0|
    ## +----+---------+----------+
    

    或原始 SQL:

    df.registerTempTable("df")
    
    sqlContext.sql("""
        SELECT MONTH(timestamp) AS month, SUM(value) AS values_sum
        FROM df
        GROUP BY MONTH(timestamp)""")
    

    请记住,聚合是由 Spark 执行的,而不是下推到外部源。通常这是一种期望的行为,但在某些情况下,您可能更愿意将聚合作为子查询执行以限制数据传输。

    【讨论】:

    • 他们有什么功能吗?
    【解决方案2】:

    此外,您可以使用 date_format 创建您希望的任何时间段。 Groupby 特定日期:

    from pyspark.sql import functions as F
    
    df.select(F.date_format('timestamp','yyyy-MM-dd').alias('day')).groupby('day').count().show()

    Groupby 特定月份(只需更改格式):

    df.select(F.date_format('timestamp','yyyy-MM').alias('month')).groupby('month').count().show()

    【讨论】:

      【解决方案3】:

      对于 pyspark >= 2.2:

      from pyspark.sql.functions import to_date
      
      df.groupBy(to_date('created_time').al)
      

      【讨论】:

        猜你喜欢
        • 2015-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-24
        • 1970-01-01
        • 1970-01-01
        • 2018-07-13
        相关资源
        最近更新 更多