web-dev-qa-db-fra.com

Comment convertir des lignes en dictionnaire dans pyspark?

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.

7
user8946942

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())
14
Cosmin

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 dicts:

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.

4
pault

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']}]
3
user9074332

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 :)

0
sneaky_lobster