Я бы не стал беспокоиться слишком насчет группировки по нескольким столбцам, кроме того, что это может сбить с толку. В этом ключе, если есть более простой и удобный способ, go для него. Без примера ввода / вывода я не уверен, что это приведет вас к тому месту, где вы пытаетесь go, но, возможно, это будет полезно:
Seq(Seq("k1" -> "v1", "k2" -> "v2")).toDS() // some basic input based on my understanding of your description
.select(explode($"value")) // flatten the array
.select("col.*") // de-nest the struct
.groupBy("_2") // one row per distinct value
.pivot("_1") // one column per distinct key
.count // or agg(first) if you want the value in each column
.show
+---+----+----+
| _2| k1| k2|
+---+----+----+
| v2|null| 1|
| v1| 1|null|
+---+----+----+
На основе того, что вы сейчас сказал, у меня сложилось впечатление, что есть много столбцов, таких как "состояние", которые не требуются для агрегирования, но должны быть в конечном результате.
Для справки, если вам не нужно было сводить , вы можете добавить столбец структуры со всеми такими вложенными полями, а затем добавить его в свою агрегацию, например: .agg(first($"myStruct"), first($"number"))
. Основное преимущество состоит в том, что в groubBy
указаны только фактические ключевые столбцы. Но при использовании pivot все становится немного странно, поэтому мы отложим эту опцию.
В этом варианте использования самый простой способ, который я мог придумать, - это разделить ваш фрейм данных и снова объединить его после агрегации используя некоторый rowkey. В этом примере я предполагаю, что "index"
подходит для этой цели:
val mehCols = dfExampleInput.columns.filter(_ != "entries").map(col)
val mehDF = dfExampleInput.select(mehCols:_*)
val aggDF = dfExampleInput
.select($"index", explode($"entries").as("entry"))
.select($"index", $"entry.*")
.groupBy("index")
.pivot("name")
.agg(first($"number"))
scala> mehDF.join(aggDF, Seq("index")).show
+-----+-----+---+----+
|index|state| A| B|
+-----+-----+---+----+
| 0| KY| 45|null|
| 1| OR| 30| 10|
+-----+-----+---+----+
Я сомневаюсь, что вы заметите большую разницу в производительности, если таковая имеется. Может быть, в крайних случаях, например: очень много meh
столбцов, или очень много сводных столбцов, или что-то в этом роде, или, может быть, вообще ничего. Лично я бы протестировал и то, и другое с вводом приличного размера, и, если не было значительной разницы, использовал бы тот, который кажется более простым в обслуживании.