收集并订购DataFrame列

时间:2017-07-10 07:23:52

标签: python scala apache-spark dataframe dataset

我有一个DataFrame,如下所示

A B C
1 3 1
1 8 2
1 5 3
2 2 1

我的输出应该是,B列是根据初始列B值

排序的
A B
1 3,1/5,3/8,2
2 2,1

我写的是像scala这样的东西

df.groupBy("A").withColumn("B",collect_list(concat("B",lit(","),"C"))

但是dint解决了我的问题。

2 个答案:

答案 0 :(得分:1)

鉴于您输入数据框为

+---+---+---+
|A  |B  |C  |
+---+---+---+
|1  |3  |1  |
|1  |8  |2  |
|1  |5  |3  |
|2  |2  |1  |
+---+---+---+

您可以将以下输出作为

+---+---------------+
|A  |B              |
+---+---------------+
|1  |[3,1, 5,3, 8,2]|
|2  |[2,1]          |
+---+---------------+

通过简单的groupByaggregations并使用functions

df.orderBy("B").groupBy("A").agg(collect_list(concat_ws(",", col("B"), col("C"))) as "B")

您可以使用udf功能获得最终所需的结果

def joinString = udf((b: mutable.WrappedArray[String]) => {
  b.mkString("/")
} )

newdf.withColumn("B", joinString(col("B"))).show(false)

你应该

+---+-----------+
|A  |B          |
+---+-----------+
|1  |3,1/5,3/8,2|
|2  |2,1        |
+---+-----------+

注意您需要import org.apache.spark.sql.functions._才能完成上述所有工作

<强>被修改

  
    

B列是根据初始B列值

排序的   

为此,您可以将orderBy部分删除为

 import org.apache.spark.sql.functions._
val newdf = df.groupBy("A").agg(collect_list(concat_ws(",", col("B"), col("C"))) as "B")

def joinString = udf((b: mutable.WrappedArray[String]) => {
  b.mkString("/")
} )

newdf.withColumn("B", joinString(col("B"))).show(false)

你应该输出

+---+-----------+
|A  |B          |
+---+-----------+
|1  |3,1/8,2/5,3|
|2  |2,1        |
+---+-----------+

答案 1 :(得分:0)

这是你可以通过使用concat_ws函数然后groupby A列并收集列表来实现的

val df1 = spark.sparkContext.parallelize(Seq(
  ( 1, 3, 1),
  (1, 8, 2),
  (1, 5, 3),
  (2, 2, 1)
)).toDF("A", "B", "C")

val result = df1.withColumn("B", concat_ws("/", $"B", $"C"))

result.groupBy("A").agg(collect_list($"B").alias("B")).show

输出:

+---+---------------+
|  A|              B|
+---+---------------+
|  1|[3/1, 8/2, 5/3]|
|  2|          [2/1]|
+---+---------------+

<强>编辑: 如果要使用列B

进行排序,可以执行以下操作
val format = udf((value : Seq[String]) => {
  value.sortBy(x => {x.split(",")(0)}).mkString("/")
})


val result = df1.withColumn("B", concat_ws(",", $"B", $"C"))
  .groupBy($"A").agg(collect_list($"B").alias("B"))
  .withColumn("B", format($"B"))

result.show()

输出:

+---+-----------+
|  A|          B|
+---+-----------+
|  1|3,1/5,3/8,2|
|  2|        2,1|
+---+-----------+

希望这有用!