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)
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
Un marco de datos con un dictado dentro de la ubicación especificada.
pd.show_versions()
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
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.
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.