计算多行的每行运行时间

时间:2017-08-23 13:24:16

标签: scala apache-spark

我的数据集如下所示:(前三列是输入,我添加了第4-6列,最后一列代表了所需的输出)

+-------------------+------+----+-------------------+-------------------+-------------------+---+----+
|          timestamp|status| msg|      end_timestamp|          start_eng|           stop_eng| --|res |
+-------------------+------+----+-------------------+-------------------+-------------------+---+----+
|2017-01-01 06:15:00| ASC_a|nice|2017-01-01 07:00:00|               null|               null|-->|  0 |
|2017-01-01 07:00:00| ASC_a|nice|2017-01-01 07:15:00|               null|               null|-->|  0 |
|2017-01-01 07:15:00| start|nice|2017-01-01 08:00:00|2017-01-01 07:15:00|               null|-->| 45 |
|2017-01-01 08:00:00| start|nice|2017-01-01 08:22:00|2017-01-01 08:00:00|               null|-->| 22 |
|2017-01-01 08:22:00| ASC_b|init|2017-01-01 09:00:00|               null|               null|-->| 38 |
|2017-01-01 09:00:00| ASC_b|init|2017-01-01 09:30:00|               null|               null|-->| 30 |
|2017-01-01 09:30:00|   end| bla|2017-01-01 10:00:00|               null|2017-01-01 09:30:00|-->|  0 |
|2017-01-01 10:00:00|   end| bla|2017-01-01 10:45:00|               null|2017-01-01 10:00:00|-->|  0 |
|2017-01-01 10:45:00| ASC_a|meas|2017-01-01 11:00:00|               null|               null|-->|  0 |
|2017-01-01 11:00:00| ASC_a|meas|2017-01-01 12:00:00|               null|               null|-->|  0 |
|2017-01-01 12:00:00| ASC_a|meas|2017-01-01 12:15:00|               null|               null|-->|  0 |
|2017-01-01 12:15:00| start|meas|2017-01-01 13:00:00|2017-01-01 12:15:00|               null|-->| 45 |
|2017-01-01 13:00:00| start|meas|2017-01-01 13:22:00|2017-01-01 13:00:00|               null|-->| 22 |
|2017-01-01 13:22:00| ASC_c|init|2017-01-01 14:00:00|               null|               null|-->| 38 |
|2017-01-01 14:00:00| ASC_c|init|2017-01-01 14:31:00|               null|               null|-->| 31 |
|2017-01-01 14:31:00|   end|meas|               null|               null|2017-01-01 14:31:00|-->|  0 |
+-------------------+------+----+-------------------+-------------------+-------------------+---+----+

我想计算从第一次出现状态开始到第一次出现状态结束时的引擎运行时间。 (状态开始和结束都出现在后续列中,因为我添加了具有explode功能的行,我以后仍然需要将它们更改为合理的值)

问题是我不知道如何计算开始和结束之间既不包含开始也不结束的行的引擎运行时。
我考虑过使用窗口函数进行计算,但我不知道如何为此指定窗口。

1 个答案:

答案 0 :(得分:0)

我终于让它为小数据集工作了。还是要在大的那个上测试它。

//get tempstat column
    val ds3 = ds2.withColumn("tempstat", when($"status".contains("ASC"), $"status").otherwise(null))
      .withColumn("tempstat_final", last($"tempstat", true).over(window))

    //remove duplicate status
    val ds5 = ds3.withColumn("new_status", when(!$"status".contains("ASC") && lag($"status", 1).over(window) =!= $"status", $"status").otherwise($"tempstat_final"))

    //get column that provides window for calculation
    val ds6 = ds5.withColumn("startFlag", when($"new_status" === "start", 1).otherwise(0))
        .withColumn("stopFlag", when($"new_status" === "end", -1).otherwise(0))
        .withColumn("bothFlags", $"startFlag" + $"stopFlag")
      .withColumn("engineFlag", sum($"bothFlags").over(Window.orderBy("timestamp")))

    //calculate runtime
    val ds7 = ds6.withColumn("runtime", when($"engineFlag" === 1,
      ((unix_timestamp(lead($"timestamp", 1).over(Window.orderBy($"timestamp"))) - unix_timestamp($"timestamp"))/60)
    ).otherwise(lit(0)))

输出和进展如下。

+-------------------+------+----+--------+--------------+----------+---------+--------+---------+----------+-------+
|          timestamp|status| msg|tempstat|tempstat_final|new_status|startFlag|stopFlag|bothFlags|engineFlag|runtime|
+-------------------+------+----+--------+--------------+----------+---------+--------+---------+----------+-------+
|2017-01-01 06:15:00| ASC_a|nice|   ASC_a|         ASC_a|     ASC_a|        0|       0|        0|         0|    0.0|
|2017-01-01 07:00:00| ASC_a|nice|   ASC_a|         ASC_a|     ASC_a|        0|       0|        0|         0|    0.0|
|2017-01-01 07:15:00| start|nice|    null|         ASC_a|     start|        1|       0|        1|         1|   45.0|
|2017-01-01 08:00:00| start|nice|    null|         ASC_a|     ASC_a|        0|       0|        0|         1|   22.0|
|2017-01-01 08:22:00| ASC_b|init|   ASC_b|         ASC_b|     ASC_b|        0|       0|        0|         1|   38.0|
|2017-01-01 09:00:00| ASC_b|init|   ASC_b|         ASC_b|     ASC_b|        0|       0|        0|         1|   30.0|
|2017-01-01 09:30:00|   end| bla|    null|         ASC_b|       end|        0|      -1|       -1|         0|    0.0|
|2017-01-01 10:00:00|   end| bla|    null|         ASC_b|     ASC_b|        0|       0|        0|         0|    0.0|
|2017-01-01 10:45:00| ASC_a|meas|   ASC_a|         ASC_a|     ASC_a|        0|       0|        0|         0|    0.0|
|2017-01-01 11:00:00| ASC_a|meas|   ASC_a|         ASC_a|     ASC_a|        0|       0|        0|         0|    0.0|
|2017-01-01 12:00:00| ASC_a|meas|   ASC_a|         ASC_a|     ASC_a|        0|       0|        0|         0|    0.0|
|2017-01-01 12:15:00| start|meas|    null|         ASC_a|     start|        1|       0|        1|         1|   45.0|
|2017-01-01 13:00:00| start|meas|    null|         ASC_a|     ASC_a|        0|       0|        0|         1|   60.0|
|2017-01-01 14:00:00| start|meas|    null|         ASC_a|     ASC_a|        0|       0|        0|         1|   60.0|
|2017-01-01 15:00:00| start|meas|    null|         ASC_a|     ASC_a|        0|       0|        0|         1|   22.0|
|2017-01-01 15:22:00| ASC_c|init|   ASC_c|         ASC_c|     ASC_c|        0|       0|        0|         1|   38.0|
|2017-01-01 16:00:00| ASC_c|init|   ASC_c|         ASC_c|     ASC_c|        0|       0|        0|         1|   31.0|
|2017-01-01 16:31:00|   end|meas|    null|         ASC_c|       end|        0|      -1|       -1|         0|    0.0|
+-------------------+------+----+--------+--------------+----------+---------+--------+---------+----------+-------++

我总是很乐意获得改进提示或其他解决方案提案,因为我还不熟悉spark / scala。