web-dev-qa-db-fra.com

PySpark DataFrames - moyen d'énumérer sans convertir en Pandas?

J'ai un très grand pyspark.sql.dataframe.DataFrame nommé df. Il me faut un moyen d’énumérer les enregistrements pour pouvoir accéder aux enregistrements avec certains index. (ou sélectionnez un groupe d'enregistrements avec une plage d'index)

Dans les pandas, je pourrais faire juste 

indexes=[2,3,6,7] 
df[indexes]

Ici, je veux quelque chose de similaire, (et sans convertir dataframe en pandas) 

Le plus proche que je peux obtenir est:

  • Énumération de tous les objets du cadre de données d'origine en:

    indexes=np.arange(df.count())
    df_indexed=df.withColumn('index', indexes)
    
    • Rechercher les valeurs dont j'ai besoin en utilisant la fonction where (). 

DES QUESTIONS:

  1. Pourquoi ça ne marche pas et comment le faire fonctionner? Comment ajouter une ligne à un cadre de données?
  2. Est-ce que ça marcherait plus tard pour faire quelque chose comme:

     indexes=[2,3,6,7] 
     df1.where("index in indexes").collect()
    
  3. Un moyen plus rapide et plus simple d'y faire face?

14
Maria Koroliuk

Si vous souhaitez que la plage de numéros ne soit pas en conflit mais ne nécessite pas de .over(partitionBy()), vous pouvez utiliser monotonicallyIncreasingId()

from pyspark.sql.functions import monotonicallyIncreasingId
df.select(monotonicallyIncreasingId().alias("rowId"),"*")

Notez cependant que les valeurs ne sont pas particulièrement "soignées". Chaque partition se voit attribuer une plage de valeurs et la sortie ne sera pas contiguë. Par exemple. 0, 1, 2, 8589934592, 8589934593, 8589934594

Ceci a été ajouté à Spark le 28 avril 2015 ici: https://github.com/Apache/spark/commit/d94cd1a733d5715792e6c4eac87f0d5c81aebbe2

11
Joe Harris

Vous pouvez certainement ajouter un tableau d’indexation, un tableau de votre choix en effet: Dans Scala, nous devons d’abord créer un tableau d’indexation:

val index_array=(1 to df.count.toInt).toArray

index_array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

Vous pouvez maintenant ajouter cette colonne à votre DF. Premièrement, pour cela, vous devez ouvrir notre DF et le récupérer sous forme de tableau, puis le compresser avec votre index_array, puis nous reconvertissons le nouveau tableau en et RDD. La dernière étape consiste à l'obtenir en tant que DF:

final_df = sc.parallelize((df.collect.map(
    x=>(x(0),x(1))) Zip index_array).map(
    x=>(x._1._1.toString,x._1._2.toString,x._2))).
    toDF("column_name")

L'indexation serait plus claire par la suite.

1
Mahdi Ghelichi