Jon*_*aus 5 apache-spark apache-spark-sql
我在Spark中有一个带有2列的数据框,group_id并且value,其中value是double.我想根据group_id每个组的顺序对数据进行分组value,然后添加第三列index,表示value组中值的排序位置.
例如,考虑以下输入数据:
+--------+-----+
|group_id|value|
+--------+-----+
|1 |1.3 |
|2 |0.8 |
|1 |3.4 |
|1 |-1.7 |
|2 |2.3 |
|2 |5.9 |
|1 |2.7 |
|1 |0.0 |
+--------+-----+
Run Code Online (Sandbox Code Playgroud)
那么输出就像是
+--------+-----+-----+
|group_id|value|index|
+--------+-----+-----+
|1 |-1.7 |1 |
|1 |0.0 |2 |
|1 |1.3 |3 |
|1 |2.7 |4 |
|1 |3.4 |5 |
|2 |0.8 |1 |
|2 |2.3 |2 |
|2 |5.9 |3 |
+--------+-----+-----+
Run Code Online (Sandbox Code Playgroud)
如果索引是从0开始并且排序是升序还是降序,则不重要.
作为后续行动,请考虑extra原始数据中存在第三列的情况,该数据对于某些(group_id, value)组合采用多个值.一个例子是:
+--------+-----+-----+
|group_id|value|extra|
+--------+-----+-----+
|1 |1.3 |1 |
|1 |1.3 |2 |
|2 |0.8 |1 |
|1 |3.4 |1 |
|1 |3.4 |2 |
|1 |3.4 |3 |
|1 |-1.7 |1 |
|2 |2.3 |1 |
|2 |5.9 |1 |
|1 |2.7 |1 |
|1 |0.0 |1 |
+--------+-----+-----+
Run Code Online (Sandbox Code Playgroud)
有没有办法添加一index列,以便extra不考虑列但仍保留?在这种情况下的输出将是
+--------+-----+-----+-----+
|group_id|value|extra|index|
+--------+-----+-----+-----+
|1 |-1.7 |1 |1 |
|1 |0.0 |1 |2 |
|1 |1.3 |1 |3 |
|1 |1.3 |2 |3 |
|1 |2.7 |1 |4 |
|1 |3.4 |1 |5 |
|1 |3.4 |2 |5 |
|1 |3.4 |3 |5 |
|2 |0.8 |1 |1 |
|2 |2.3 |1 |2 |
|2 |5.9 |1 |3 |
+--------+-----+-----+-----+
Run Code Online (Sandbox Code Playgroud)
我知道可以通过复制数据,删除extra列来实现这一点
extra列distinct操作,这将导致原始示例中的数据index使用原始解决方案计算列但是,这将涉及大量额外的计算和开销.
您可以使用Window函数创建基于以下value分区的排名列group_id:
from pyspark.sql.window import Window
from pyspark.sql.functions import rank, dense_rank
# Define window
window = Window.partitionBy(df['group_id']).orderBy(df['value'])
# Create column
df.select('*', rank().over(window).alias('index')).show()
+--------+-----+-----+
|group_id|value|index|
+--------+-----+-----+
| 1| -1.7| 1|
| 1| 0.0| 2|
| 1| 1.3| 3|
| 1| 2.7| 4|
| 1| 3.4| 5|
| 2| 0.8| 1|
| 2| 2.3| 2|
| 2| 5.9| 3|
+--------+-----+-----+
Run Code Online (Sandbox Code Playgroud)
因为,您首先选择'*',您还使用上面的代码保留所有其他变量.但是,您的第二个示例显示您正在查找该函数dense_rank(),该函数作为没有间隙的排名列:
df.select('*', dense_rank().over(window).alias('index'))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2811 次 |
| 最近记录: |