J'ai des données enregistrées dans une base de données postgreSQL. J'interroge ces données en utilisant Python2.7 et je les transforme en un Pandas DataFrame. Cependant, la dernière colonne de ce dataframe contient un dictionnaire (ou une liste?) De valeurs. Le DataFrame ressemble à ceci:
[1] df
Station ID Pollutants
8809 {"a": "46", "b": "3", "c": "12"}
8810 {"a": "36", "b": "5", "c": "8"}
8811 {"b": "2", "c": "7"}
8812 {"c": "11"}
8813 {"a": "82", "c": "15"}
Je dois diviser cette colonne en colonnes séparées pour que le DataFrame ressemble à ceci:
[2] df2
Station ID a b c
8809 46 3 12
8810 36 5 8
8811 NaN 2 7
8812 NaN NaN 11
8813 82 NaN 15
Le principal problème que j'ai, c'est que les listes ne sont pas de la même longueur. Mais toutes les listes ne contiennent que les 3 mêmes valeurs: a, b et c. Et ils apparaissent toujours dans le même ordre (un premier, b deuxième, c troisième).
Le code suivant utilisé pour fonctionner et retourner exactement ce que je voulais (df2).
[3] df
[4] objs = [df, pandas.DataFrame(df['Pollutant Levels'].tolist()).iloc[:, :3]]
[5] df2 = pandas.concat(objs, axis=1).drop('Pollutant Levels', axis=1)
[6] print(df2)
J'exécutais ce code la semaine dernière et cela fonctionnait bien. Mais maintenant, mon code est cassé et j'obtiens cette erreur de la ligne [4]:
IndexError: out-of-bounds on slice (end)
Je n'ai apporté aucune modification au code mais j'obtiens maintenant l'erreur. Je pense que cela est dû au fait que ma méthode n'est ni robuste ni appropriée.
Toutes suggestions ou conseils sur la façon de diviser cette colonne de listes en colonnes séparées seraient très appréciés!
EDIT: Je pense que les méthodes .tolist () et .apply ne fonctionnent pas sur mon code car il s'agit d'une chaîne unicode, c'est-à-dire:
#My data format
u{'a': '1', 'b': '2', 'c': '3'}
#and not
{u'a': '1', u'b': '2', u'c': '3'}
Les données sont importées de la base de données postgreSQL dans ce format. Avez-vous de l'aide ou des idées sur ce problème? y a-t-il un moyen de convertir l'unicode?
la source
iloc
partieiloc[:, :3]
suppose-t-il qu'il y aura 3 éléments, et peut-être que les tranches de données plus récentes n'en ont que 1 ou 2 (par exemple, il n'y a pas deb
like inindex 8813
)?Réponses:
Pour convertir la chaîne en un dict réel, vous pouvez le faire
df['Pollutant Levels'].map(eval)
. Ensuite, la solution ci-dessous peut être utilisée pour convertir le dict en différentes colonnes.En utilisant un petit exemple, vous pouvez utiliser
.apply(pd.Series)
:Pour le combiner avec le reste de la dataframe, vous pouvez
concat
les autres colonnes avec le résultat ci-dessus:En utilisant votre code, cela fonctionne également si je laisse de côté la
iloc
partie:la source
pd.DataFrame(df[col].tolist())
longtemps, je n'y ai jamais penséapply(pd.Series)
. Très agréable.DataFrame(df['col'].tolist())
approche est un peu plus rapide que l'approche appliquer!df[col].map(eval)
avant de le convertir en DataFrameJe sais que la question est assez ancienne, mais je suis arrivé ici à la recherche de réponses. Il existe actuellement un moyen meilleur (et plus rapide) de le faire en utilisant
json_normalize
:Cela évite des fonctions d'application coûteuses ...
la source
.json
fichiers proviennent de différentes sources et ce ne sont pas toujours les mêmes colonnes qui sont imbriquées. J'ai essayé de trouver un moyen de créer une liste de colonnes contenant des dictionnaires, mais je n'arrive pas à y parvenirfrom pandas.io.json import json_normalize
meta_prefix
etrecord_prefix
. Bien que je ne puisse pas faire fonctionner cela avec mon dataframe (le dataframe final est correct dans mon cas mais je voudrais appliquer les préfixes).Essayez ceci: les données renvoyées par SQL doivent être converties en dictée. ou est-ce que
"Pollutant Levels"
c'est maintenantPollutants'
la source
La réponse de Merlin est meilleure et super facile, mais nous n'avons pas besoin d'une fonction lambda. L'évaluation du dictionnaire peut être ignorée en toute sécurité par l'une des deux méthodes suivantes, comme illustré ci-dessous:
Voie 1: Deux étapes
Voie 2: Les deux étapes ci-dessus peuvent être combinées en une seule fois:
la source
Je recommande fortement la méthode extraire la colonne 'Polluants':
df_pollutants = pd.DataFrame(df['Pollutants'].values.tolist(), index=df.index)
c'est beaucoup plus rapide que
df_pollutants = df['Pollutants'].apply(pd.Series)
quand la taille de df est géante.
la source
apply
l'ensemble de la trame de données est géré par des pandas, mais quand il s'agit devalues
jouer uniquement avec lenumpy ndarrays
qui est intrinsèquement plus rapide en raison du fait qu'il a desc
implémentations pures .Vous pouvez utiliser
join
avecpop
+tolist
. La performance est comparable à celleconcat
avecdrop
+tolist
, mais certains peuvent trouver ce nettoyeur de syntaxe:Analyse comparative avec d'autres méthodes:
la source
Une solution en ligne est la suivante:
la source
my_df = pd.DataFrame.from_dict(my_dict, orient='index', columns=['my_col'])
.. aurait analysé correctement le dict (en mettant chaque clé de dict dans une colonne df séparée et les valeurs de clé dans des lignes df), de sorte que les dicts ne seraient pas écrasés dans une seule colonne en premier lieu.
la source
J'ai concaténé ces étapes dans une méthode, vous devez passer uniquement le dataframe et la colonne qui contient le dict à développer:
la source
la source