我想根据另一列中测试的条件创建组标签。特别是,如果有directionChange.equalTo(1)
的值,我想开始一个新的段(标签)。结果应在segmentNr
列中给出,我的代码生成的结果位于nSegment
。
我认为不可能以这种方式进行类似的分配。
最后,我想计算不同的方面,例如每个段的值的和,平均值,最大值(不在问题的范围内)。
输入示例:
+---+-----+---------------+---------+--------+
| id|value|directionChange|segmentNr|nSegment|
+---+-----+---------------+---------+--------+
| 1| 11.0| 0| 1| 1|
| 2|-22.0| 1| 2| 1|
| 3| 34.0| 0| 2| 1|
| 4|-47.0| 1| 3| 1|
| 5| 61.0| 1| 4| 1|
| 6| 22.0| 0| 4| 1|
| 7| 5.0| 0| 4| 1|
| 8| -7.0| 1| 5| 1|
+---+-----+---------------+---------+--------+
使用输入数据集添加新列的功能:
public static Dataset<Row> createSegments(Dataset<Row> dataset, String columnName, int start, String newColumnName) throws Exception
{
int test = 1;
Dataset<Row> resultDataset = dataset.withColumn(newColumnName, //
functions.when(dataset.col(columnName).equalTo(1), (start = start + 1))//
.otherwise(start));
return resultDataset;
}
该函数调用如下:
dataset = createSegments(dataset, "directionChange", 0, "nSegment");
答案 0 :(得分:0)
这可以使用Window
函数完成。但是,由于您没有用于对数据进行分区的列,因此对于大型数据集而言可能会非常慢。这可以通过在partitionBy(column)
对象下使用Window
来改进。但是,这需要一个好的列进行分区,最终的结果也会分成几部分。
解决方案背后的想法是在directionChange
列排序时生成id
列的累积总和。在斯卡拉:
val window = Window.orderBy("id").rowsBetween(Window.unboundedPreceding, Window.currentRow)
val df2 = dataset.withColumn("nSegment", sum($"directionChange").over(window) + 1)
Java代码:
WindowSpec window = Window.orderBy("id").rowsBetween(Window.unboundedPreceding(), Window.currentRow());
Dataset<Row> df2 = dataset.withColumn("nSegment", functions.sum("directionChange").over(window));
在旧版本的Spark(&lt; 2.1.0)中使用:
rowsBetween(Long.MinValue, 0)
这将创建一个新列nSegment
,它等于输入数据中的segmentNr
。对于下一步,您可以使用groupBy("nSegment").agg(...)
计算每个细分的不同指标。