Pandas: El almacenamiento de un dict en un DataFrame falla

Creado en 4 oct. 2017  ·  3Comentarios  ·  Fuente: pandas-dev/pandas

Ejemplo de código, un ejemplo copiable y pegable si es posible

Ambos ejemplos a continuación fallan con el mismo error

df = pd.DataFrame(index=[0, 1, 2], columns=['a', 'b'])

df.loc[0, 'a'] = dict(x=2)
df.iloc[0, 0] = dict(x=2)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-282-62f3ee5ff885> in <module>()
      1 # file_map.loc[file_no, 'Q_step_length'] = dict(a=1)
      2 df = pd.DataFrame(index=[0, 1, 2], columns=['a', 'b'])
----> 3 df.iloc[0, 0] = dict(x=2)
      4 df['a'] = df['a'].apply(lambda x: x[0] if not pd.isnull(x) else x)
      5 df

...\lib\site-packages\pandas\core\indexing.py in __setitem__(self, key, value)
    177             key = com._apply_if_callable(key, self.obj)
    178         indexer = self._get_setitem_indexer(key)
--> 179         self._setitem_with_indexer(indexer, value)
    180 
    181     def _has_valid_type(self, k, axis):

...\lib\site-packages\pandas\core\indexing.py in _setitem_with_indexer(self, indexer, value)
    603 
    604             if isinstance(value, (ABCSeries, dict)):
--> 605                 value = self._align_series(indexer, Series(value))
    606 
    607             elif isinstance(value, ABCDataFrame):

...\lib\site-packages\pandas\core\indexing.py in _align_series(self, indexer, ser, multiindex_indexer)
    743             return ser.reindex(ax)._values
    744 
--> 745         raise ValueError('Incompatible indexer with Series')
    746 
    747     def _align_frame(self, indexer, df):

ValueError: Incompatible indexer with Series

Esto funciona, pero está colocando una lista en el marco de datos

df[0, 'a'] = [dict(x=2)]

Es posible obtener el dict directamente en el marco de datos usando una construcción muy poco elegante como esta:

df['a'] = df['a'].apply(lambda x: x[0] if not pd.isnull(x) else x)

Descripción del problema

Dado que es posible almacenar un dictado en un marco de datos, intentar una asignación como la anterior no debería fallar. Soy consciente de que df.loc[...] = dict(...) asignará valores en el dict a las columnas correspondientes si están presentes (¿está documentado?) y tiene sus propios problemas, pero este comportamiento no debería aplicarse al acceder una única ubicación de la trama de datos

Rendimiento esperado

Un marco de datos con un dictado dentro de la ubicación especificada.

Salida de pd.show_versions()

VERSIONES INSTALADAS

compromiso: Ninguno
pitón: 3.5.4.final.0
bits de Python: 64
SO: Windows
Lanzamiento del sistema operativo: 10
máquina: AMD64
Procesador: Intel64 Familia 6 Modelo 58 Paso 9, GenuineIntel
orden de bytes: pequeño
LC_ALL: Ninguno
IDIOMA: Ninguno
LOCAL: Ninguno.Ninguno

pandas: 0.20.3
PyTest: Ninguno
pipa: 9.0.1
herramientas de configuración: 36.5.0
Citón: 0,26
numpy: 1.13.1
espía: 0.19.1
matriz: ninguno
Python: 6.1.0
esfinge: Ninguno
chivo expiatorio: 0.4.1
dateutil: 2.6.1
Pytz: 2017.2
bloque: Ninguno
cuello de botella: Ninguno
tablas: ninguna
exprnumero: Ninguno
pluma: Ninguno
matplotlib: 2.0.2
openpyxl: Ninguno
xlrd: Ninguno
xlwt: Ninguno
xlsxwriter: Ninguno
lxml: Ninguno
bs4: Ninguno
html5lib: 0.9999999
sqlalchemy: Ninguno
pymysql: Ninguno
psycopg2: Ninguno
jinja2: 2.9.6
s3fs: Ninguno
pandas_gbq: Ninguno
pandas_datareader: Ninguno

Indexing

Comentario más útil

Encontró el mismo problema, tenía dos pensamientos:

Almacenar un dict dentro de un DataFrame es inusual, pero hay casos válidos en los que el software puede estar usando Pandas como una forma de representar y manipular datos de estilo clave/valor arbitrarios donde los datos se indexan de una manera que tiene sentido para la representación del panel.

El comportamiento de que la indexación basada en la ubicación actualizará las columnas en función de las claves/valores de un diccionario proporcionado fue una sorpresa para mí. Esta es una característica de conveniencia interesante que tiene sentido cuando no se hace referencia a una columna explícita. Por ejemplo, al proporcionar:

df.loc[row, :] = dict(key1=value1, key2=value2)

Tiene sentido que las claves del diccionario se escriban como columnas y que df.loc[row, key1] == value1 . Sin embargo, al proporcionar un índice de columna explícito, inferir las columnas de destino de un diccionario proporcionado es (para mí) contrario a la intuición. Si en cambio proporciono:

df.loc[row, col] = dict(key=value)

Estoy indicando explícitamente que quiero almacenar el valor completo en la columna col , y espero que el diccionario se inserte tal como está.

De todos modos, estoy de acuerdo con @jreback en que esto es algo no idiomático, PERO simpatizo con el problema original planteado por @andreas-thomik. Encontré un problema en el que tratar de almacenar un dictado en un elemento de un marco de datos usando esta sintaxis tenía sentido para el problema particular al que me enfrentaba, por lo que no está completamente solo con esta solicitud.

Todos 3 comentarios

esto es bastante no idiomático, y estás bastante solo aquí. podría hacerlo simplemente usando una lista/tupla a su alrededor

In [14]: df.loc[0, 'a'] = [dict(x=2)]

In [15]: df
Out[15]: 
            a    b
0  [{'x': 2}]  NaN
1         NaN  NaN
2         NaN  NaN

Encontró el mismo problema, tenía dos pensamientos:

Almacenar un dict dentro de un DataFrame es inusual, pero hay casos válidos en los que el software puede estar usando Pandas como una forma de representar y manipular datos de estilo clave/valor arbitrarios donde los datos se indexan de una manera que tiene sentido para la representación del panel.

El comportamiento de que la indexación basada en la ubicación actualizará las columnas en función de las claves/valores de un diccionario proporcionado fue una sorpresa para mí. Esta es una característica de conveniencia interesante que tiene sentido cuando no se hace referencia a una columna explícita. Por ejemplo, al proporcionar:

df.loc[row, :] = dict(key1=value1, key2=value2)

Tiene sentido que las claves del diccionario se escriban como columnas y que df.loc[row, key1] == value1 . Sin embargo, al proporcionar un índice de columna explícito, inferir las columnas de destino de un diccionario proporcionado es (para mí) contrario a la intuición. Si en cambio proporciono:

df.loc[row, col] = dict(key=value)

Estoy indicando explícitamente que quiero almacenar el valor completo en la columna col , y espero que el diccionario se inserte tal como está.

De todos modos, estoy de acuerdo con @jreback en que esto es algo no idiomático, PERO simpatizo con el problema original planteado por @andreas-thomik. Encontré un problema en el que tratar de almacenar un dictado en un elemento de un marco de datos usando esta sintaxis tenía sentido para el problema particular al que me enfrentaba, por lo que no está completamente solo con esta solicitud.

@aaclayton esto está relacionado con #18955. Podríamos/deberíamos admitir mejor la configuración de escalares de dictados (y otros iterables). Aunque es un poco complicado.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

scls19fr picture scls19fr  ·  3Comentarios

MatzeB picture MatzeB  ·  3Comentarios

songololo picture songololo  ·  3Comentarios

Ashutosh-Srivastav picture Ashutosh-Srivastav  ·  3Comentarios

ebran picture ebran  ·  3Comentarios