Convertir Python dict en un marco de datos

299

Tengo un diccionario de Python como el siguiente:

{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}

Las claves son fechas Unicode y los valores son enteros. Me gustaría convertir esto en un marco de datos de pandas al tener las fechas y sus valores correspondientes como dos columnas separadas. Ejemplo: col1: Fechas col2: DateValue (las fechas siguen siendo Unicode y los valores de fecha siguen siendo enteros)

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

Cualquier ayuda en esta dirección sería muy apreciada. No puedo encontrar recursos en los documentos de pandas para ayudarme con esto.

Sé que una solución podría ser convertir cada par clave-valor en este dict, en un dict para que toda la estructura se convierta en un dict de dicts, y luego podamos agregar cada fila individualmente al marco de datos. Pero quiero saber si hay una manera más fácil y más directa de hacerlo.

Hasta ahora he intentado convertir el dict en un objeto en serie, pero esto no parece mantener la relación entre las columnas:

s  = Series(my_dict,index=my_dict.keys())
anonuser0428
fuente
Intenté convertir el dict en un objeto en serie con las fechas como índice pero eso no coincidió con los valores correspondientes por alguna razón.
anonuser0428
El código ha sido publicado. Quiero preguntar si hay una manera de crear un marco de datos sin crear un dictado de dictados y luego agregar cada fila por separado.
anonuser0428
1
¿Qué es una "fecha Unicode"? ¿Te refieres a una fecha ISO 8601 ?
Peter Mortensen

Respuestas:

461

El error aquí, es desde llamar al constructor DataFrame con valores escalares (donde espera que los valores sean una lista / dict / ... es decir, que tengan varias columnas):

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

Puede tomar los elementos del diccionario (es decir, los pares clave-valor):

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

Pero creo que tiene más sentido pasar el constructor de la serie:

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
Andy Hayden
fuente
44
@ user1009091 Me di cuenta de lo que significa el error ahora, básicamente dice "Lo que estoy viendo es una serie, así que use el constructor de la serie".
Andy Hayden
1
Gracias, muy útil. ¿Podría explicar cuál es la diferencia entre usar este método y usar DataFrame.from_dict ()? Su método (que utilicé) devuelve type = pandas.core.frame.DataFrame, mientras que el otro devuelve type = class 'pandas.core.frame.DataFrame'. ¿Alguna posibilidad de que puedas explicar la diferencia y cuándo cada método es apropiado? Gracias de antemano :)
Optimesh
Ambos son similares, from_dicttienen un kwarg orientado, por lo que podría usarlo si quisiera evitar la transposición. Hay pocas opciones con from_dict, debajo del capó no es realmente diferente de usar el constructor DataFrame.
Andy Hayden
54
Estoy viendo pandas.core.common.PandasError: DataFrame constructor not properly called!desde el primer ejemplo
allthesignals
18
@allthesignals agregar lista () alrededor de d.items funciona: pd.DataFrame (list (d.items ()), columnas = ['Fecha', 'Valor de fecha'])
sigurdb
142

Al convertir un diccionario en un marco de datos de pandas donde desea que las claves sean las columnas de dicho marco de datos y los valores sean los valores de fila, puede simplemente poner corchetes alrededor del diccionario de esta manera:

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

¡Me ha ahorrado algunos dolores de cabeza, así que espero que ayude a alguien!

EDITAR: en los documentos de pandas, una opción para el dataparámetro en el constructor DataFrame es una lista de diccionarios. Aquí estamos pasando una lista con un diccionario en ella.

cheevahagadog
fuente
66
Sí, también hice esto pero agregué .T para transponer.
Anton vBR
1
Funciona bien, pero no sé por qué tenemos que hacerlo así.
hui chen
¿Y si quiero una columna de éstos para ser utilizado como índice
om tripathi
102

Como se explica en otra respuesta, usar pandas.DataFrame()directamente aquí no actuará como usted piensa.

Lo que puedes hacer es usar pandas.DataFrame.from_dictcon 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
ntg
fuente
1
¿podemos encadenar esto con algún renamemétodo para establecer también los nombres del índice y las columnas de una vez?
Ciprian Tomoiagă
44
buen punto. Un ejemplo sería: ...., orient = 'index'). Rename (columnas = {0: 'foobar'})
ntg
1
También puede especificar pandas.DataFrame.from_dict (..., orient = 'index', columnas = ['foo', 'bar']), esto es de la fuente mencionada anteriormente .
spen.smith
buen punto, esto es cierto para los pandas .22 que fue después de la respuesta original ...
Actualicé
69

Pase los elementos del diccionario al constructor DataFrame y proporcione los nombres de las columnas. Después de eso, analice la Datecolumna para obtener Timestampvalores.

Tenga en cuenta la diferencia entre python 2.xy 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: (requiere una 'lista' adicional)

df = pd.DataFrame(list(data.items()), columns=['Date', 'DateValue'])
df['Date'] = pd.to_datetime(df['Date'])
Viktor Kerkez
fuente
3
Esto me da:PandasError: DataFrame constructor not properly called!
Chris Nielsen
18
@ChrisNielsen Probablemente estés usando python3. Deberías probar:df = pd.DataFrame(list(data.items()), columns=['Date', 'DateValue'])
Viktor Kerkez
Esta es la mejor respuesta porque muestra lo que debe hacerse en Python 3.
ifly6
10

Los pandas tienen una función incorporada para la conversión de dict a marco de datos.

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

Para sus datos, puede convertirlos de la siguiente manera:

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)
Suat Atan PhD
fuente
2
Esa es una solución realmente mala, ya que guarda las claves del diccionario como índice.
Un economista
6
pd.DataFrame({'date' : dict_dates.keys() , 'date_value' : dict_dates.values() })
Nader Hisham
fuente
5

También puede pasar las claves y los valores del diccionario al nuevo marco de datos, así:

import pandas as pd

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

En mi caso, quería que las claves y los valores de un dict fueran columnas y valores de DataFrame. Entonces, lo único que funcionó para mí fue:

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)
Artem Zaika
fuente
5

Esto es lo que funcionó para mí, ya que quería tener una columna de índice separada

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

Acepta un dict como argumento y devuelve un marco de datos con las claves del dict como índice y los valores como una columna.

def dict_to_df(d):
    df=pd.DataFrame(d.items())
    df.set_index(0, inplace=True)
    return df
en primer lugar
fuente
tome un dict, devuelve un marco de datos
primero
3

Así es como funcionó para mí:

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

espero que esto ayude

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

Si no encapsula yourDict.keys()dentro de list(), entonces terminará con todas sus claves y valores colocados en cada fila de cada columna. Me gusta esto:

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...

Pero al agregar list(), el resultado se ve así:

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 ...

Códigos NL23
fuente
0

Me he encontrado con esto varias veces y tengo un diccionario de ejemplo que creé a partir de una función get_max_Path(), y me devuelve el diccionario de muestra:

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

Para convertir esto en un marco de datos, ejecuté lo siguiente:

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

Devuelve un marco de datos simple de dos columnas con un índice separado:

index 0 0 2 0.309750 1 3 0.441318

Simplemente cambie el nombre de las columnas usando f.rename(columns={'index': 'Column1', 0: 'Column2'}, inplace=True)

Bryan Butler
fuente
0

Creo que puede hacer algunos cambios en su formato de datos cuando crea un diccionario, luego puede convertirlo fácilmente a DataFrame:

entrada:

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

salida:

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

entrada:

aframe=DataFrame(a)

salida: será su DataFrame

Solo necesita usar algo de edición de texto en algún lugar como Sublime o tal vez Excel.

Arman Nemat Pasand
fuente