Convertir Python dict en une trame de données


299

J'ai un dictionnaire Python comme celui-ci:

{u'2012-06-08': 388,
 u'2012-06-09': 388,
 u'2012-06-10': 388,
 u'2012-06-11': 389,
 u'2012-06-12': 389,
 u'2012-06-13': 389,
 u'2012-06-14': 389,
 u'2012-06-15': 389,
 u'2012-06-16': 389,
 u'2012-06-17': 389,
 u'2012-06-18': 390,
 u'2012-06-19': 390,
 u'2012-06-20': 390,
 u'2012-06-21': 390,
 u'2012-06-22': 390,
 u'2012-06-23': 390,
 u'2012-06-24': 390,
 u'2012-06-25': 391,
 u'2012-06-26': 391,
 u'2012-06-27': 391,
 u'2012-06-28': 391,
 u'2012-06-29': 391,
 u'2012-06-30': 391,
 u'2012-07-01': 391,
 u'2012-07-02': 392,
 u'2012-07-03': 392,
 u'2012-07-04': 392,
 u'2012-07-05': 392,
 u'2012-07-06': 392}

Les clés sont des dates Unicode et les valeurs sont des entiers. Je voudrais convertir cela en une trame de données pandas en ayant les dates et leurs valeurs correspondantes dans deux colonnes distinctes. Exemple: col1: Dates col2: DateValue (les dates sont toujours Unicode et les valeurs de date sont toujours des entiers)

     Date         DateValue
0    2012-07-01    391
1    2012-07-02    392
2    2012-07-03    392
.    2012-07-04    392
.    ...           ...
.    ...           ...

Toute aide dans ce sens serait très appréciée. Je n'arrive pas à trouver de ressources sur les documents des pandas pour m'aider.

Je sais qu'une solution pourrait être de convertir chaque paire clé-valeur dans ce dict, en un dict afin que toute la structure devienne un dict de dict, puis nous pouvons ajouter chaque ligne individuellement à la trame de données. Mais je veux savoir s'il existe un moyen plus simple et plus direct de le faire.

Jusqu'à présent, j'ai essayé de convertir le dict en un objet série, mais cela ne semble pas maintenir la relation entre les colonnes:

s  = Series(my_dict,index=my_dict.keys())

J'ai essayé de convertir le dict en un objet série avec les dates comme index mais cela ne correspond pas aux dates avec les valeurs correspondantes pour une raison quelconque.
anonuser0428

le code a été affiché. Je souhaite savoir s'il existe un moyen de créer une trame de données sans créer un dict-of-dicts, puis en ajoutant chaque ligne séparément.
anonuser0428

1
Qu'est-ce qu'une "date Unicode"? Voulez-vous dire une date ISO 8601 ?
Peter Mortensen

Réponses:


461

L'erreur ici est depuis l'appel du constructeur DataFrame avec des valeurs scalaires (où il s'attend à ce que les valeurs soient une liste / dict / ... c'est-à-dire qu'elles aient plusieurs colonnes):

pd.DataFrame(d)
ValueError: If using all scalar values, you must must pass an index

Vous pouvez prendre les éléments du dictionnaire (c'est-à-dire les paires clé-valeur):

In [11]: pd.DataFrame(d.items())  # or list(d.items()) in python 3
Out[11]:
             0    1
0   2012-07-02  392
1   2012-07-06  392
2   2012-06-29  391
3   2012-06-28  391
...

In [12]: pd.DataFrame(d.items(), columns=['Date', 'DateValue'])
Out[12]:
          Date  DateValue
0   2012-07-02        392
1   2012-07-06        392
2   2012-06-29        391

Mais je pense qu'il est plus logique de passer le constructeur de la série:

In [21]: s = pd.Series(d, name='DateValue')
Out[21]:
2012-06-08    388
2012-06-09    388
2012-06-10    388

In [22]: s.index.name = 'Date'

In [23]: s.reset_index()
Out[23]:
          Date  DateValue
0   2012-06-08        388
1   2012-06-09        388
2   2012-06-10        388

4
@ user1009091 J'ai réalisé ce que signifie l'erreur maintenant, c'est essentiellement dire "Ce que je vois est une série, alors utilisez le constructeur de la série".
Andy Hayden

1
Merci - très utile. Pourriez-vous peut-être expliquer quelle est la différence entre l'utilisation de cette méthode et l'utilisation de DataFrame.from_dict ()? Votre méthode (que j'ai utilisée) renvoie type = pandas.core.frame.DataFrame, tandis que l'autre renvoie type = class 'pandas.core.frame.DataFrame'. Avez-vous une chance d'expliquer la différence et quand chaque méthode est appropriée? Merci d'avance :)
Optimesh

ils sont tous les deux similaires, from_dicta un kwarg orient, donc je pourrais l'utiliser si je voulais éviter la transposition. Il y a peu d'options avec from_dict, sous le capot, ce n'est pas vraiment différent de l'utilisation du constructeur DataFrame.
Andy Hayden

54
Je vois pandas.core.common.PandasError: DataFrame constructor not properly called!du premier exemple
allthesignals

18
@allthesignals l'ajout de list () autour de d.items fonctionne: pd.DataFrame (list (d.items ()), columns = ['Date', 'DateValue'])
sigurdb

142

Lors de la conversion d'un dictionnaire en un cadre de données pandas où vous voulez que les clés soient les colonnes dudit cadre de données et les valeurs soient les valeurs de ligne, vous pouvez simplement mettre des crochets autour du dictionnaire comme ceci:

>>> dict_ = {'key 1': 'value 1', 'key 2': 'value 2', 'key 3': 'value 3'}
>>> pd.DataFrame([dict_])

    key 1     key 2     key 3
0   value 1   value 2   value 3

Cela m'a évité quelques maux de tête, donc j'espère que cela aide quelqu'un là-bas!

EDIT: Dans les documents pandas, une option pour le dataparamètre dans le constructeur DataFrame est une liste de dictionnaires. Ici, nous passons une liste avec un dictionnaire dedans.


6
Oui j'ai aussi fait ça mais j'ai ajouté .T pour transposer.
Anton vBR

1
Cela fonctionne bien mais je ne sais pas pourquoi nous devons le faire comme ça.
hui chen

que faire si je veux utiliser une de ces colonnes comme index
om tripathi

102

Comme expliqué sur une autre réponse en utilisant pandas.DataFrame() directement ici n'agira pas comme vous le pensez.

Ce que vous pouvez faire, c'est utiliser pandas.DataFrame.from_dictavec orient='index':

In[7]: pandas.DataFrame.from_dict({u'2012-06-08': 388,
 u'2012-06-09': 388,
 u'2012-06-10': 388,
 u'2012-06-11': 389,
 u'2012-06-12': 389,
 .....
 u'2012-07-05': 392,
 u'2012-07-06': 392}, orient='index', columns=['foo'])
Out[7]: 
            foo
2012-06-08  388
2012-06-09  388
2012-06-10  388
2012-06-11  389
2012-06-12  389
........
2012-07-05  392
2012-07-06  392

1
pouvons-nous enchaîner cela avec n'importe quelle renameméthode pour définir également les noms de l'index et des colonnes en une seule fois?
Ciprian Tomoiagă

4
bon point. Un exemple serait: ...., orient = 'index'). Rename (colonnes = {0: 'foobar'})
ntg

1
Vous pouvez également spécifier pandas.DataFrame.from_dict (..., orient = 'index', colonnes = ['foo', 'bar']), cela provient de la source listée ci-dessus .
spen.smith

bon point, cela est vrai de pandas .22 qui était après la réponse d'origine ... Mise à jour de ma réponse ...
ntg

69

Passez les éléments du dictionnaire au constructeur DataFrame et donnez les noms des colonnes. Après cela, analysez la Datecolonne pour obtenir des Timestampvaleurs.

Notez la différence entre python 2.x et 3.x:

En python 2.x:

df = pd.DataFrame(data.items(), columns=['Date', 'DateValue'])
df['Date'] = pd.to_datetime(df['Date'])

En Python 3.x: (nécessitant une 'liste' supplémentaire)

df = pd.DataFrame(list(data.items()), columns=['Date', 'DateValue'])
df['Date'] = pd.to_datetime(df['Date'])

3
Cela me donne:PandasError: DataFrame constructor not properly called!
Chris Nielsen

18
@ChrisNielsen Vous utilisez probablement python3. Vous devriez essayer:df = pd.DataFrame(list(data.items()), columns=['Date', 'DateValue'])
Viktor Kerkez

C'est la meilleure réponse car elle montre ce qui doit être fait en Python 3.
ifly6


10

Les pandas ont une fonction intégrée pour la conversion de dict en trame de données.

pd.DataFrame.from_dict (dictionaryObject, orient = 'index')

Pour vos données, vous pouvez les convertir comme ci-dessous:

import pandas as pd
your_dict={u'2012-06-08': 388,
 u'2012-06-09': 388,
 u'2012-06-10': 388,
 u'2012-06-11': 389,
 u'2012-06-12': 389,
 u'2012-06-13': 389,
 u'2012-06-14': 389,
 u'2012-06-15': 389,
 u'2012-06-16': 389,
 u'2012-06-17': 389,
 u'2012-06-18': 390,
 u'2012-06-19': 390,
 u'2012-06-20': 390,
 u'2012-06-21': 390,
 u'2012-06-22': 390,
 u'2012-06-23': 390,
 u'2012-06-24': 390,
 u'2012-06-25': 391,
 u'2012-06-26': 391,
 u'2012-06-27': 391,
 u'2012-06-28': 391,
 u'2012-06-29': 391,
 u'2012-06-30': 391,
 u'2012-07-01': 391,
 u'2012-07-02': 392,
 u'2012-07-03': 392,
 u'2012-07-04': 392,
 u'2012-07-05': 392,
 u'2012-07-06': 392}

your_df_from_dict=pd.DataFrame.from_dict(your_dict,orient='index')
print(your_df_from_dict)

2
C'est vraiment une mauvaise solution, car il enregistre les clés de dictionnaire en tant qu'index.
Un économiste

6
pd.DataFrame({'date' : dict_dates.keys() , 'date_value' : dict_dates.values() })

5

Vous pouvez également simplement passer les clés et les valeurs du dictionnaire au nouveau dataframe, comme ceci:

import pandas as pd

myDict = {<the_dict_from_your_example>]
df = pd.DataFrame()
df['Date'] = myDict.keys()
df['DateValue'] = myDict.values()

5

Dans mon cas, je voulais que les clés et les valeurs d'un dict soient des colonnes et des valeurs de DataFrame. Donc, la seule chose qui a fonctionné pour moi était:

data = {'adjust_power': 'y', 'af_policy_r_submix_prio_adjust': '[null]', 'af_rf_info': '[null]', 'bat_ac': '3500', 'bat_capacity': '75'} 

columns = list(data.keys())
values = list(data.values())
arr_len = len(values)

pd.DataFrame(np.array(values, dtype=object).reshape(1, arr_len), columns=columns)

5

C'est ce qui a fonctionné pour moi, car je voulais avoir une colonne d'index distincte

df = pd.DataFrame.from_dict(some_dict, orient="index").reset_index()
df.columns = ['A', 'B']

3

Accepte un dict comme argument et renvoie une trame de données avec les clés du dict comme index et les valeurs comme colonne.

def dict_to_df(d):
    df=pd.DataFrame(d.items())
    df.set_index(0, inplace=True)
    return df

prendre un dict, retourne une trame de données
tout d'abord

3

Voici comment cela a fonctionné pour moi:

df= pd.DataFrame([d.keys(), d.values()]).T
df.columns= ['keys', 'values']  # call them whatever you like

J'espère que ça aide


1
d = {'Date': list(yourDict.keys()),'Date_Values': list(yourDict.values())}
df = pandas.DataFrame(data=d)

Si vous n'encapsulez pas l' yourDict.keys()intérieur de list(), alors vous vous retrouverez avec toutes vos clés et valeurs placées dans chaque ligne de chaque colonne. Comme ça:

Date \ 0 (2012-06-08, 2012-06-09, 2012-06-10, 2012-06-1...
1 (2012-06-08, 2012-06-09, 2012-06-10, 2012-06-1...
2 (2012-06-08, 2012-06-09, 2012-06-10, 2012-06-1...
3 (2012-06-08, 2012-06-09, 2012-06-10, 2012-06-1...
4 (2012-06-08, 2012-06-09, 2012-06-10, 2012-06-1...

Mais en ajoutant list()alors le résultat ressemble à ceci:

Date Date_Values 0 2012-06-08 388 1 2012-06-09 388 2 2012-06-10 388 3 2012-06-11 389 4 2012-06-12 389 ...


0

J'ai rencontré cela plusieurs fois et j'ai un exemple de dictionnaire que j'ai créé à partir d'une fonction get_max_Path(), et il retourne l'exemple de dictionnaire:

{2: 0.3097502930247044, 3: 0.4413177909384636, 4: 0.5197224051562838, 5: 0.5717654946470984, 6: 0.6063959031223476, 7: 0.6365209824708223, 8: 0.655918861281035, 9: 0.680844386645206}

Pour convertir cela en une trame de données, j'ai exécuté ce qui suit:

df = pd.DataFrame.from_dict(get_max_path(2), orient = 'index').reset_index()

Renvoie une trame de données simple à deux colonnes avec un index séparé:

index 0 0 2 0.309750 1 3 0.441318

Renommez simplement les colonnes en utilisant f.rename(columns={'index': 'Column1', 0: 'Column2'}, inplace=True)


0

Je pense que vous pouvez apporter des modifications à votre format de données lorsque vous créez un dictionnaire, puis vous pouvez facilement le convertir en DataFrame:

contribution:

a={'Dates':['2012-06-08','2012-06-10'],'Date_value':[388,389]}

production:

{'Date_value': [388, 389], 'Dates': ['2012-06-08', '2012-06-10']}

contribution:

aframe=DataFrame(a)

sortie: sera votre DataFrame

Vous avez juste besoin d'utiliser une édition de texte dans un endroit comme Sublime ou peut-être Excel.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.