web-dev-qa-db-fra.com

Extraire les valeurs de colonne de Dataframe en tant que liste dans Apache Spark

Je voudrais convertir une colonne de chaîne d'un dataframe à une liste. Ce que je peux trouver dans l’API Dataframe, c’est RDD; j’ai donc essayé de le reconvertir en RDD d’abord, puis d’appliquer la fonction toArray au RDD. Dans ce cas, la longueur et le SQL fonctionnent parfaitement. Cependant, le résultat que j'ai obtenu de RDD a des crochets autour de chaque élément comme ceci [A00001]. Je me demandais s'il existe un moyen approprié de convertir une colonne en liste ou de supprimer les crochets.

Toute suggestion serait appréciée. Je vous remercie!

60
SH Y.

Cela devrait retourner la collection contenant une liste unique:

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()

Sans le mappage, vous obtenez simplement un objet Row, qui contient toutes les colonnes de la base de données.

Gardez à l'esprit que cela vous donnera probablement une liste de tout type. Si vous souhaitez spécifier le type de résultat, vous pouvez utiliser .asInstanceOf [YOUR_TYPE] dans le mappage r => r(0).asInstanceOf[YOUR_TYPE]

P.S. En raison de la conversion automatique, vous pouvez ignorer la partie .rdd.

81
Niemand

Avec Spark 2.x et Scala 2.11

Je pense à 3 façons possibles de convertir les valeurs d'une colonne spécifique en liste

Extraits de code communs pour toutes les approches

import org.Apache.spark.sql.SparkSession

val spark = SparkSession.builder.getOrCreate    
import spark.implicits._ // for .toDf() method

val df = Seq(
    ("first", 2.0),
    ("test", 1.5),
    ("choose", 8.0)
  ).toDF("id", "val")

Approche 1

df.select("id").collect().map(_(0)).toList
// res9: List[Any] = List(one, two, three)

Qu'est-ce qui se passe maintenant? Nous recueillons des données sur le pilote avec collect() et prenons l'élément zéro dans chaque enregistrement. 

Cela ne pourrait pas être un excellent moyen de le faire, améliorons-le à l'approche suivante.


Approche 2

df.select("id").rdd.map(r => r(0)).collect.toList 
//res10: List[Any] = List(one, two, three)

Comment ça va mieux? Nous avons réparti la charge de transformation de la carte entre les travailleurs plutôt que par un seul pilote. 

Je sais que rdd.map(r => r(0)) ne vous semble pas élégant. Alors abordons-le dans la prochaine approche.


Approche 3

df.select("id").map(r => r.getString(0)).collect.toList 
//res11: List[String] = List(one, two, three)

Ici, nous ne convertissons pas DataFrame en RDD. Regardez map, il n'acceptera pas r => r(0) (ou _(0)) comme approche précédente en raison de problèmes de codeur dans DataFrame. Donc, finissez par utiliser r => r.getString(0) et cela sera traité dans les prochaines versions de Spark.

Conclusion

Toutes les options donnent la même sortie mais 2 et 3 sont efficaces, enfin la 3ème est efficace et élégante (je pense).

Le lien de cahier de données qui sera disponible jusqu’à 6 mois à partir du 2017/05/20

34
mrsrinivas

Je sais que la réponse donnée et demandée est supposée être pour Scala. Je fournis donc simplement un petit extrait de code Python au cas où un utilisateur de PySpark serait curieux. La syntaxe est similaire à la réponse donnée, mais pour sortir correctement la liste, je dois en réalité référencer le nom de la colonne une deuxième fois dans la fonction de mappage et je n'ai pas besoin de l'instruction select.

c'est-à-dire un DataFrame, contenant une colonne nommée "Raw"

Pour obtenir chaque valeur de ligne dans "Raw" combinée en une liste où chaque entrée est une valeur de ligne de "Raw", j'utilise simplement:

MyDataFrame.rdd.map(lambda x: x.Raw).collect()
14
abby sobh

Dans Scala et Spark 2+, essayez ceci (en supposant que votre nom de colonne est "s"): df.select('s).as[String].collect

4
kanielc
     sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets

ça marche parfaitement

0
Shaina Raza