【问题标题】:group by hour using time alone (ex:10:00:00 AM) in spark sql in java?在java中的spark sql中单独使用时间(例如:10:00:00 AM)按小时分组?
【发布时间】:2017-08-08 17:25:03
【问题描述】:

您好,我想以 1 小时和 15 分钟为单位对我的记录进行分组。

所以 我的数据集是,

    |Date   |Time       | speed |avg|
    |1/1/2016|10:00:00 AM|     21| 10|
    |1/1/2016|10:00:00 PM|     45| 10|
    |1/1/2016|11:15:00 AM|     35| 10|
    |1/1/2016|12:15:00 PM|     25| 20|
    |1/1/2016|01:30:00 AM|     15| 30|

从上面的数据集中,我想对平均速度和平均计数进行分组: 我在 spark sql 中尝试过的示例查询是:

spark.sql(select Time, avg(speed),count(avg) from dataset group by Time)

【问题讨论】:

  • 为什么您的数据中有 AM/PM?它已经是 24 小时制了。
  • @philantrovert ..嗨,伙计,我把它改成了 12h 格式?.. 这是一个错字
  • 您的意思是按一天中的小时分组,而不考虑分钟数?
  • 是的,应该不分白天。

标签: sql apache-spark apache-spark-sql


【解决方案1】:

您可以使用要分组的数据创建一个新列:

import org.apache.spark.sql.functions;
df = df.withColumn("hour", functions.concat(
                functions.split(df.col("Time"), " ").getItem(1), 
                functions.lit(":"), 
                functions.split(df.col("Time"), ":").getItem(0)
            ));
df.show();

+--------+-----------+-----+---+-----+
|    Date|       Time|speed|avg| hour|
+--------+-----------+-----+---+-----+
|1/1/2016|10:00:00 AM|   21| 10|10:AM|
|1/1/2016|10:00:00 PM|   45| 10|10:PM|
|1/1/2016|11:15:00 AM|   35| 10|11:AM|
|1/1/2016|12:15:00 PM|   25| 20|12:PM|
|1/1/2016|01:30:00 AM|   15| 30|01:AM|
+--------+-----------+-----+---+-----+

然后您可以在这个新列上进行聚合:

df = df.groupBy("hour")
       .agg(functions.avg("speed"), functions.count("avg"));
df.show();

+-----+----------+----------+
| hour|avg(speed)|count(avg)|
+-----+----------+----------+
|10:AM|      21.0|         1|
|12:PM|      25.0|         1|
|11:AM|      35.0|         1|
|10:PM|      45.0|         1|
|01:AM|      15.0|         1|
+-----+----------+----------+

如果您也需要按日期查找,也可以在 groupby 中添加日期:

df.groupBy("hour", "Date")
    .agg(functions.avg("speed"), functions.count("avg"))
    .show()

+-----+--------+----------+----------+
| hour|    Date|avg(speed)|count(avg)|
+-----+--------+----------+----------+
|01:AM|1/1/2016|      15.0|         1|
|10:AM|1/1/2016|      21.0|         1|
|10:PM|1/1/2016|      45.0|         1|
|12:PM|1/1/2016|      25.0|         1|
|11:AM|1/1/2016|      35.0|         1|
+-----+--------+----------+----------+

【讨论】:

  • 谢谢它的工作,你知道如何在 15 分钟内做同样的事情吗?
【解决方案2】:

从时间中提取小时并分组使用

SELECT Extract(HOUR From TIME) AS time1, Avg(speed),Count(Avg) FROM DATASET GROUP BY time1

【讨论】:

  • 遇到异常:输入不匹配 'From' 期望 {')'、','}(第 1 行,第 20 行)== SQL == SELECT Extract(HOUR From Time)
【解决方案3】:
val df = sc.parallelize(Array(
("1/1/2016","10:00:00 AM","21","10"),
("1/1/2016","10:00:00 PM","45","10"),
("1/1/2016","11:15:00 AM","35","10"),
("1/1/2016","12:15:00 PM","25","20"),
("1/1/2016","01:30:00 AM","15","30"))).toDF("date", "time", "speed", "avg")

df.registerTempTable("dataset")

您需要将字符串转换为日期/时间类型,然后在group by子句中提取小时

sqlContext.sql("""
     SELECT hour(from_unixtime(unix_timestamp(concat_ws(" ", date, time), "dd/MM/YYYY hh:mm:ss aa") ) ) as hours, 
     avg(speed) as avg_speed, count(avg) as cnt_avg 
     from dataset 
     group by hour(from_unixtime(unix_timestamp(concat_ws(" ", date, time), "dd/MM/YYYY hh:mm:ss aa") ) )
 """).show

+-----+---------+-------+
|hours|avg_speed|cnt_avg|
+-----+---------+-------+
|    1|     15.0|      1|
|   10|     21.0|      1|
|   11|     35.0|      1|
|   12|     25.0|      1|
|   22|     45.0|      1|
+-----+---------+-------+

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    相关资源
    最近更新 更多