Pandas: Le stockage d'un dict dans un DataFrame échoue

Créé le 4 oct. 2017  ·  3Commentaires  ·  Source: pandas-dev/pandas

Exemple de code, un exemple à copier-coller si possible

Les deux exemples ci-dessous échouent avec la même erreur

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

Cela fonctionne, mais place une liste dans le dataframe

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

Il est possible d'obtenir le dict directement dans le dataframe en utilisant une construction très inélégante comme celle-ci :

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

Description du problème

Puisqu'il est possible de stocker un dict dans une trame de données, essayer une affectation comme ci-dessus ne devrait pas échouer. Je suis conscient que df.loc[...] = dict(...) attribuera des valeurs dans le dict aux colonnes correspondantes si elles sont présentes (est-ce documenté ?) et a ses propres problèmes, mais ce comportement ne devrait pas s'appliquer lors de l'accès un emplacement unique de la trame de données

Production attendue

Une trame de données avec un dict à l'intérieur de l'emplacement spécifié.

Sortie de pd.show_versions()

VERSIONS INSTALLÉES

validation : aucune
Python : 3.5.4.final.0
python-bits : 64
Système d'exploitation : Windows
Version du système d'exploitation : 10
ordinateur : AMD64
processeur : Intel64 famille 6 modèle 58 pas à pas 9, GenuineIntel
ordre des octets : peu
LC_ALL : aucun
LANGUE : Aucune
LOCALE : Aucun.Aucun

pandas : 0.20.3
pytest : aucun
pip : 9.0.1
outils de configuration : 36.5.0
Cyton : 0,26
numérique : 1.13.1
scipy : 0.19.1
xarray : aucun
IPython : 6.1.0
sphinx : Aucun
pigeon : 0.4.1
dateutil : 2.6.1
pytz : 2017.2
bloc: Aucun
goulot d'étranglement : aucun
tableaux : aucun
numexpr : Aucun
plume : Aucune
matplotlib : 2.0.2
openpyxl : Aucun
xlrd : aucun
xlwt : aucun
xlsxwriter : Aucun
lxml : Aucun
bs4 : aucun
html5lib : 0,9999999
sqlalchemy : Aucun
pymysql : aucun
psycopg2 : aucun
jinja2 : 2.9.6
s3fs : aucun
pandas_gbq : aucun
pandas_datareader : aucun

Indexing

Commentaire le plus utile

Rencontré le même problème, j'ai eu deux pensées:

Le stockage d'un dict dans un DataFrame est inhabituel, mais il existe des cas valables où le logiciel peut utiliser Pandas comme moyen de représenter et de manipuler des données arbitraires de style clé/valeur où les données sont indexées d'une manière qui a du sens pour la représentation du panneau.

Le comportement selon lequel l'indexation basée sur l'emplacement mettra à jour les colonnes en fonction des clés/valeurs d'un dictionnaire fourni m'a surpris. Il s'agit d'une fonctionnalité pratique intéressante qui a du sens lorsqu'une colonne explicite n'est pas référencée. Par exemple, lors de la fourniture :

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

Il est logique que les clés du dictionnaire soient écrites sous forme de colonnes et que df.loc[row, key1] == value1 . Cependant, lorsque vous fournissez un index de colonne explicite, déduire les colonnes cibles à partir d'un dictionnaire fourni est (pour moi) contre-intuitif. Si je fournis plutôt :

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

J'indique explicitement que je veux stocker la valeur entière dans la colonne col , et je m'attendrais à ce que le dictionnaire soit inséré tel quel.

Quoi qu'il en soit, je suis d'accord avec @jreback que c'est quelque peu non idiomatique MAIS je suis sympathique au problème initial soulevé par @andreas-thomik. J'ai rencontré un problème où essayer de stocker un dict dans un élément d'une trame de données en utilisant cette syntaxe avait du sens pour le problème particulier auquel je faisais face, donc il n'est pas entièrement seul avec cette demande.

Tous les 3 commentaires

c'est assez non idiomatique, et vous êtes à peu près seul ici. vous pouvez le faire en utilisant simplement une liste/tuple autour de lui

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

Rencontré le même problème, j'ai eu deux pensées:

Le stockage d'un dict dans un DataFrame est inhabituel, mais il existe des cas valables où le logiciel peut utiliser Pandas comme moyen de représenter et de manipuler des données arbitraires de style clé/valeur où les données sont indexées d'une manière qui a du sens pour la représentation du panneau.

Le comportement selon lequel l'indexation basée sur l'emplacement mettra à jour les colonnes en fonction des clés/valeurs d'un dictionnaire fourni m'a surpris. Il s'agit d'une fonctionnalité pratique intéressante qui a du sens lorsqu'une colonne explicite n'est pas référencée. Par exemple, lors de la fourniture :

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

Il est logique que les clés du dictionnaire soient écrites sous forme de colonnes et que df.loc[row, key1] == value1 . Cependant, lorsque vous fournissez un index de colonne explicite, déduire les colonnes cibles à partir d'un dictionnaire fourni est (pour moi) contre-intuitif. Si je fournis plutôt :

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

J'indique explicitement que je veux stocker la valeur entière dans la colonne col , et je m'attendrais à ce que le dictionnaire soit inséré tel quel.

Quoi qu'il en soit, je suis d'accord avec @jreback que c'est quelque peu non idiomatique MAIS je suis sympathique au problème initial soulevé par @andreas-thomik. J'ai rencontré un problème où essayer de stocker un dict dans un élément d'une trame de données en utilisant cette syntaxe avait du sens pour le problème particulier auquel je faisais face, donc il n'est pas entièrement seul avec cette demande.

@aaclayton ceci est lié à #18955 . Nous pourrions/devrions mieux prendre en charge la définition des scalaires des dicts (et d'autres itérables). C'est un peu délicat cependant.

Cette page vous a été utile?
0 / 5 - 0 notes