Python Pyspark-在多列上保留收集列表和收集集的顺序
我有下面的pyspark数据框Python Pyspark-在多列上保留收集列表和收集集的顺序,python,dataframe,apache-spark,pyspark,group-by,Python,Dataframe,Apache Spark,Pyspark,Group By,我有下面的pyspark数据框 Column_1 Column_2 Column_3 Column_4 1 A U1 12345 1 A A1 549BZ4G 预期产出: 第1列和第2列上的分组依据。收集集合第3列和第4列,同时保留输入数据帧中的顺序。它应该与输入的顺序相同。第3列和第4列之间的排序没有相关性。两者都必须保留输入数据帧顺序 Column_1 Column_2 Column_3 Column_4 1
Column_1 Column_2 Column_3 Column_4
1 A U1 12345
1 A A1 549BZ4G
预期产出:
第1列和第2列上的分组依据。收集集合第3列和第4列,同时保留输入数据帧中的顺序。它应该与输入的顺序相同。第3列和第4列之间的排序没有相关性。两者都必须保留输入数据帧顺序
Column_1 Column_2 Column_3 Column_4
1 A U1,A1 12345,549BZ4G
到目前为止,我尝试的是:
我第一次尝试使用窗口方法。其中,我按第1列和第2列划分,并按第1列和第2列排序。然后,我按照第1列和第2列进行分组,并在第3列和第4列进行收集
我没有得到预期的输出。我的结果如下
Column_1 Column_2 Column_3 Column_4
1 A U1,A1 549BZ4G,12345
我还尝试使用单调递增的id创建一个索引,然后按索引排序,然后执行GROUPBY和collect集合以获得输出。但还是没有运气
它是由字母数字和数字值引起的吗?
如何保持第3列和第4列在输入中的顺序,而不改变顺序。使用spark的
单向递增id
功能来维持顺序。您可以找到有关它的更多信息
使用collect\u列表
顶部的array\u distinct
来获得不同的值并维护顺序
#InputDF
# +----+----+----+-------+
# |col1|col2|col3| col4|
# +----+----+----+-------+
# | 1| A| U1| 12345|
# | 1| A| A1|549BZ4G|
# | 1| A| U1|123456 |
# +----+----+----+-------+
df1 = df.withColumn("id", F.monotonically_increasing_id()).groupby("Col1", "col2").agg(
F.array_distinct(F.collect_list("col4")).alias("Col4"),F.array_distinct(F.collect_list("col3")).alias("Col3"))
df1.select("col1", "col2", F.array_join("col3", ",").alias("col3"), F.array_join("col4", ",").alias("col4")).show(truncate=False)
# +----+----+-----+---------------------+
# |col1|col2|col3 |col4 |
# +----+----+-----+---------------------+
# |1 |A |U1,A1|12345,549BZ4G,123456 |
# +----+----+-----+---------------------+
使用struct怎么样
val result = df.groupBy(
"Column_1", "Column_2"
).agg(
collect_list(
struct(col("Column_3"), col("Column_4"))
).alias("coll")
).select(
col("Column_1"), col("Column_2"), col("coll.Column_3"), col("coll.Column_4")
)
这应该会产生预期的结果。
诀窍是struct保留命名元素,以便您可以通过引用它们。存取器。它也适用于ArrayType(StructType)
通过struct对并置的概念进行分组感觉很自然,因为这是您试图在这里保留的结构关系
从理论上讲,您甚至可能不想解包结构,因为这些值似乎具有依赖性。spark中的所有收集函数(collect\u set,collect\u list)都是不确定的,因为收集结果的顺序取决于底层数据帧中的行顺序,而底层数据帧又是不确定的
因此,总结一下,使用spark collect函数不能真正保持顺序
ref-我不确定为什么它没有显示正确的结果,对我来说,这是按照预期的结果- 输入
df_a = spark.createDataFrame([(1,'A','U1','12345'),(1,'A','A1','549BZ4G')],[ "col_1","col_2","col_3","col_4"])
df_a.show()
+-----+-----+--------+----------------+
|col_1|col_2| col_3| col_4|
+-----+-----+--------+----------------+
| 1| A|[U1, A1]|[12345, 549BZ4G]|
+-----+-----+--------+----------------+
逻辑
from pyspark.sql import functions as F
df_a = df_a.groupBy('col_1','col_2').agg(F.collect_list('col_3').alias('col_3'), F.collect_list('col_4').alias('col_4'))
输出
df_a = spark.createDataFrame([(1,'A','U1','12345'),(1,'A','A1','549BZ4G')],[ "col_1","col_2","col_3","col_4"])
df_a.show()
+-----+-----+--------+----------------+
|col_1|col_2| col_3| col_4|
+-----+-----+--------+----------------+
| 1| A|[U1, A1]|[12345, 549BZ4G]|
+-----+-----+--------+----------------+
我尝试使用单调递增的id。我尝试使用collect set而不是collect list,因为我希望只保留不同的值,并且我没有得到column4的预期输出。您是否尝试使用collect set,但仍然获得了预期的输出?collect_set正在更改您提到的顺序。我更新了代码,在
collect\u列表
的顶部使用了array\u distinct
。这可能是collect_集合的一个解决方法。希望能有帮助。谢谢你@Loka。我会尝试一下并更新youThank you@milos。我会试试这个