Je travaille sur un dataframe avec deux colonnes, mvv et count.
+---+-----+
|mvv|count|
+---+-----+
| 1 | 5 |
| 2 | 9 |
| 3 | 3 |
| 4 | 1 |
Je voudrais obtenir deux listes contenant les valeurs mvv et la valeur de comptage. Quelque chose comme
mvv = [1,2,3,4]
count = [5,9,3,1]
Donc, j'ai essayé le code suivant: La première ligne devrait renvoyer une liste de lignes python. Je voulais voir la première valeur:
mvv_list = mvv_count_df.select('mvv').collect()
firstvalue = mvv_list[0].getInt(0)
Mais j'obtiens un message d'erreur avec la deuxième ligne:
AttributeError: getInt
python
apache-spark
pyspark
spark-dataframe
a.moussa
la source
la source
list(df.select('mvv').toPandas()['mvv'])
. Arrow a été intégré à PySpark, ce qui a considérablement accélérétoPandas
. N'utilisez pas les autres approches si vous utilisez Spark 2.3+. Voir ma réponse pour plus de détails sur l'analyse comparative.Réponses:
Voyez, pourquoi cette façon que vous faites ne fonctionne pas. Tout d'abord, vous essayez d'obtenir un entier à partir d'un type de ligne , la sortie de votre collecte est comme ceci:
Si vous prenez quelque chose comme ça:
Vous obtiendrez la
mvv
valeur. Si vous voulez toutes les informations du tableau, vous pouvez prendre quelque chose comme ceci:Mais si vous essayez la même chose pour l'autre colonne, vous obtenez:
Cela se produit car il
count
s'agit d'une méthode intégrée. Et la colonne porte le même nom quecount
. Une solution de contournement pour ce faire est de modifier le nom de la colonne decount
en_count
:Mais cette solution de contournement n'est pas nécessaire, car vous pouvez accéder à la colonne à l'aide de la syntaxe du dictionnaire:
Et cela fonctionnera enfin!
la source
select('count')
utilisation comme ceci:count_list = [int(i.count) for i in mvv_list.collect()]
j'ajouterai l'exemple à la réponse.[i.['count'] for i in mvv_list.collect()]
travaille pour rendre explicite l'utilisation de la colonne nommée 'count' et non lacount
fonctionSuivre une ligne donne la liste que vous voulez.
la source
Cela vous donnera tous les éléments sous forme de liste.
la source
Le code suivant vous aidera
la source
Sur mes données, j'ai ces points de repère:
0,52 seconde
0,271 seconde
0,427 seconde
le résultat est le même
la source
toLocalIterator
place,collect
cela devrait même être plus efficace en mémoire[row[col] for row in data.toLocalIterator()]
Si vous obtenez l'erreur ci-dessous:
Ce code résoudra vos problèmes:
la source
J'ai effectué une analyse comparative et
list(mvv_count_df.select('mvv').toPandas()['mvv'])
c'est la méthode la plus rapide. Je suis très surpris.J'ai exécuté les différentes approches sur 100 mille / 100 millions d'ensembles de données de lignes en utilisant un cluster i3.xlarge à 5 nœuds (chaque nœud a 30,5 Go de RAM et 4 cœurs) avec Spark 2.4.5. Les données ont été uniformément réparties sur 20 fichiers Parquet compressés avec une seule colonne.
Voici les résultats de l'analyse comparative (durées d'exécution en secondes):
Règles d'or à suivre lors de la collecte de données sur le nœud du pilote:
toPandas
a été considérablement amélioré dans Spark 2.3 . Ce n'est probablement pas la meilleure approche si vous utilisez une version Spark antérieure à 2.3.Voir ici pour plus de détails / résultats d'analyse comparative.
la source
Une solution possible consiste à utiliser la
collect_list()
fonction depyspark.sql.functions
. Cela agrégera toutes les valeurs de colonne dans un tableau pyspark qui est converti en une liste python lors de la collecte:la source