Spark collect_list cambia data_type da array a stringa
Sto avendo una seguente aggregazione
val df_date_agg = df
.groupBy($"a",$"b",$"c") .agg(sum($"d").alias("data1"),sum($"e").alias("data2")) .groupBy($"a")
.agg(collect_list(array($"b",$"c",$"data1")).alias("final_data1"), collect_list(array($"b",$"c",$"data2")).alias("final_data2"))
Qui sto facendo un po 'di aggregazione e raccogliendo il risultato con collect_list. In precedenza stavamo usando Spark 1 e mi dava i seguenti tipi di dati.
|-- final_data1: array (nullable = true)
| |-- element: string (containsNull = true)
|-- final_data2: array (nullable = true)
| |-- element: string (containsNull = true)
Ora dobbiamo migrare a Spark 2 ma stiamo andando sotto lo schema.
|-- final_data1: array (nullable = true)
| |-- element: array (containsNull = true)
| | |-- element: string (containsNull = true)
|-- final_data1: array (nullable = true)
| |-- element: array (containsNull = true)
| | |-- element: string (containsNull = true)
Ottenere il first()record di seguito è la differenza
spark 1.6
[2020-09-26, Ayush, 103.67] => datatype string
spark 2
WrappedArray(2020-09-26, Ayush, 103.67)
Come posso mantenere lo stesso tipo di dati?
Modifica: ho provato a utilizzare Concat
Un modo in cui ho ottenuto uno schema esatto come Spark 1.6 è utilizzando concat in questo modo
val df_date_agg = df
.groupBy($"msisdn",$"event_date",$"network") .agg(sum($"data_mou").alias("data_mou_dly"),sum($"voice_mou").alias("voice_mou_dly")) .groupBy($"msisdn")
.agg(collect_list(concat(lit("["),lit($"event_date"),lit(","),lit($"network"),lit(","),lit($"data_mou_dly"),lit("]")))
Influirà sulle prestazioni del mio codice? C'è un modo migliore per farlo?
Risposte
Dal momento che vuoi una rappresentazione di stringa di un array, che ne dici di lanciare l'array in una stringa come questa?
val df_date_agg = df
.groupBy($"a",$"b",$"c") .agg(sum($"d").alias("data1"),sum($"e").alias("data2")) .groupBy($"a")
.agg(collect_list(array($"b",$"c",$"data1") cast "string").alias("final_data1"), collect_list(array($"b",$"c",$"data2") cast "string").alias("final_data2"))
Potrebbe semplicemente essere quello che stava facendo la tua vecchia versione di Spark.
La soluzione che proponi probabilmente funzionerebbe allo stesso modo, ma litnon è necessario racchiudere i riferimenti di colonna ( lit($"event_date")). $"event_date"è abbastanza.
Riempire le colonne final1 e final2 risolverebbe questo problema.
val data = Seq((1,"A", "B"), (1, "C", "D"), (2,"E", "F"), (2,"G", "H"), (2,"I", "J"))
val df = spark.createDataFrame(
data
).toDF("col1", "col2", "col3")
val old_df = df.groupBy(col("col1")).agg(
collect_list(
array(
col("col2"),
col("col3")
)
).as("final")
)
val new_df = old_df.select(col("col1"), flatten(col("final")).as("final_new"))
println("Input Dataframe")
df.show(false)
println("Old schema format")
old_df.show(false)
old_df.printSchema()
println("New schema format")
new_df.show(false)
new_df.printSchema()
Produzione:
Input Dataframe
+----+----+----+
|col1|col2|col3|
+----+----+----+
|1 |A |B |
|1 |C |D |
|2 |E |F |
|2 |G |H |
|2 |I |J |
+----+----+----+
Old schema format
+----+------------------------+
|col1|final |
+----+------------------------+
|1 |[[A, B], [C, D]] |
|2 |[[E, F], [G, H], [I, J]]|
+----+------------------------+
root
|-- col1: integer (nullable = false)
|-- final: array (nullable = true)
| |-- element: array (containsNull = true)
| | |-- element: string (containsNull = true)
New schema format
+----+------------------+
|col1|final_new |
+----+------------------+
|1 |[A, B, C, D] |
|2 |[E, F, G, H, I, J]|
+----+------------------+
root
|-- col1: integer (nullable = false)
|-- final_new: array (nullable = true)
| |-- element: string (containsNull = true)
Nel tuo caso specifico
val df_date_agg = df
.groupBy($"a",$"b",$"c") .agg(sum($"d").alias("data1"),sum($"e").alias("data2")) .groupBy($"a")
.agg(collect_list(array($"b",$"c",$"data1")).alias("final_data1"), collect_list(array($"b",$"c",$"data2")).alias("final_data2"))
.select(flatten(col("final_data1").as("final_data1"), flatten(col("final_data2).as("final_data2))