J'ai un DataFrame (df) dans pyspark, en lisant à partir d'une table Hive:
df=spark.sql('select * from <table_name>')
+++++++++++++++++++++++++++++++++++++++++++
| Name | URL visited |
+++++++++++++++++++++++++++++++++++++++++++
| person1 | [google,msn,yahoo] |
| person2 | [fb.com,airbnb,wired.com] |
| person3 | [fb.com,google.com] |
+++++++++++++++++++++++++++++++++++++++++++
Quand j'ai essayé ce qui suit, j'ai une erreur
df_dict = dict(Zip(df['name'],df['url']))
"TypeError: Zip argument #1 must support iteration."
type(df.name) is of 'pyspark.sql.column.Column'
Comment créer un dictionnaire comme celui-ci, qui peut être répété plus tard
{'person1':'google','msn','yahoo'}
{'person2':'fb.com','airbnb','wired.com'}
{'person3':'fb.com','google.com'}
Appréciez vos pensées et votre aide.
Je pense que vous pouvez essayer row.asDict()
, ce code s'exécute directement sur l'exécuteur, et vous n'avez pas à collecter les données sur le pilote.
Quelque chose comme:
df.rdd.map(lambda row: row.asDict())
Si vous vouliez vos résultats dans un dictionnaire python, vous pouvez utiliser collect()
1 pour importer les données dans la mémoire locale, puis massez la sortie comme vous le souhaitez.
Collectez d'abord les données:
df_dict = df.collect()
#[Row(Name=u'person1', URL visited=[u'google', u'msn,yahoo']),
# Row(Name=u'person2', URL visited=[u'fb.com', u'airbnb', u'wired.com']),
# Row(Name=u'person3', URL visited=[u'fb.com', u'google.com'])]
Cela renvoie une liste de pyspark.sql.Row
objets. Vous pouvez facilement le convertir en une liste de dict
s:
df_dict = [{r['Name']: r['URL visited']} for r in df_dict]
#[{u'person1': [u'google', u'msn,yahoo']},
# {u'person2': [u'fb.com', u'airbnb', u'wired.com']},
# {u'person3': [u'fb.com', u'google.com']}]
1 Sachez que pour les grands ensembles de données, cette opération peut être lente et potentiellement échouer avec une erreur de mémoire insuffisante. Vous devriez considérer si c'est ce que vous voulez vraiment faire en premier car vous perdrez les avantages de la parallélisation de spark en apportant les données dans la mémoire locale.
Que diriez-vous d'utiliser la méthode pyspark Row.as_Dict()
? Cela fait partie de l'API Dataframe (qui, je crois, est l'API "recommandée" au moment de la rédaction) et ne vous obligerait pas du tout à utiliser l'API RDD.
df_list_of_dict = [row.asDict() for row in df.collect()]
type(df_list_of_dict), type(df_list_of_dict[0])
#(<class 'list'>, <class 'dict'>)
df_list_of_dict
#[{'person1': ['google','msn','yahoo']},
# {'person2': ['fb.com','airbnb','wired.com']},
# {'person3': ['fb.com','google.com']}]
Donné:
+++++++++++++++++++++++++++++++++++++++++++
| Name | URL visited |
+++++++++++++++++++++++++++++++++++++++++++
| person1 | [google,msn,yahoo] |
| person2 | [fb.com,airbnb,wired.com] |
| person3 | [fb.com,google.com] |
+++++++++++++++++++++++++++++++++++++++++++
Cela devrait fonctionner:
df_dict = df \
.rdd \
.map(lambda row: {row[0]: row[1]}) \
.collect()
df_dict
#[{'person1': ['google','msn','yahoo']},
# {'person2': ['fb.com','airbnb','wired.com']},
# {'person3': ['fb.com','google.com']}]
De cette façon, vous récupérez juste après le traitement.
S'il vous plaît, faites-moi savoir si cela fonctionne pour vous :)