Après:
val df = Seq((1, Vector(2, 3, 4)), (1, Vector(2, 3, 4))).toDF("Col1", "Col2")
J'ai ce DataFrame dans Apache Spark:
+------+---------+
| Col1 | Col2 |
+------+---------+
| 1 |[2, 3, 4]|
| 1 |[2, 3, 4]|
+------+---------+
Comment puis-je convertir cela en:
+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------+------+
| 1 | 2 | 3 | 4 |
| 1 | 2 | 3 | 4 |
+------+------+------+------+
Une solution qui ne convertit pas vers et depuis RDD:
df.select($"Col1", $"Col2"(0) as "Col2", $"Col2"(1) as "Col3", $"Col2"(2) as "Col3")
Ou discutable plus agréable:
val nElements = 3
df.select(($"Col1" +: Range(0, nElements).map(idx => $"Col2"(idx) as "Col" + (idx + 2)):_*))
La taille d'une colonne d'un tableau Spark n'est pas fixe, vous pourriez par exemple avoir:
+----+------------+
|Col1| Col2|
+----+------------+
| 1| [2, 3, 4]|
| 1|[2, 3, 4, 5]|
+----+------------+
Il n’ya donc aucun moyen d’obtenir le - montant des colonnes et de les créer. Si vous savez que la taille est toujours la même, vous pouvez définir nElements
comme ceci:
val nElements = df.select("Col2").first.getList(0).size
Juste pour donner la version Pyspark de la réponse de sgvd . Si la colonne de tableau est dans Col2
, cette instruction select déplacera la première nElements
de chaque tableau dans Col2
dans leurs propres colonnes:
from pyspark.sql import functions as F
df.select([F.col('Col2').getItem(i) for i in range(nElements)])
Ajoutez simplement à sgvd's solution:
Si la taille n'est pas toujours la même, vous pouvez définir nElements de la manière suivante:
val nElements = df.select(size('Col2).as("Col2_count"))
.select(max("Col2_count"))
.first.getInt(0)
Vous pouvez utiliser une carte:
df.map {
case Row(col1: Int, col2: mutable.WrappedArray[Int]) => (col1, col2(0), col2(1), col2(2))
}.toDF("Col1", "Col2", "Col3", "Col4").show()