Pandas: Armazenar um dict em um DataFrame falha

Criado em 4 out. 2017  ·  3Comentários  ·  Fonte: pandas-dev/pandas

Exemplo de código, um exemplo de copiar e colar, se possível

Ambos os exemplos abaixo falham com o mesmo erro

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

Isso funciona, mas está colocando uma lista no dataframe

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

É possível obter o dict diretamente no dataframe usando uma construção muito deselegante como esta:

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

Descrição do Problema

Como é possível armazenar um dict em um dataframe, tentar uma atribuição como acima não deve falhar. Estou ciente de que df.loc[...] = dict(...) atribuirá valores no dict às colunas correspondentes se houver (isso está documentado?) e tem seus próprios problemas, mas esse comportamento não deve se aplicar ao acessar um único local do dataframe

Saída esperada

Um dataframe com um dict dentro do local especificado.

Saída de pd.show_versions()

VERSÕES INSTALADAS

compromisso: Nenhum
python: 3.5.4.final.0
bits python: 64
SO: Windows
Versão do SO: 10
máquina: AMD64
processador: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
byteorder: pouco
LC_ALL: Nenhum
LAN: Nenhum
LOCAL: Nenhum. Nenhum

pandas: 0,20,3
pytest: Nenhum
pip: 9.0.1
ferramentas de configuração: 36.5.0
Cíton: 0,26
numpy: 1.13.1
scip: 0.19.1
xarray: Nenhum
IPython: 6.1.0
esfinge: nenhuma
paty: 0.4.1
dateutil: 2.6.1
pytz: 2017.2
bloco: Nenhum
gargalo: nenhum
tabelas: Nenhuma
numexpr: Nenhum
pena: nenhuma
matplotlib: 2.0.2
openpyxl: Nenhum
xlrd: Nenhum
xlwt: Nenhum
xlsxwriter: Nenhum
lxml: Nenhum
bs4: Nenhum
html5lib: 0,9999999
sqlalchemy: Nenhum
pymysql: Nenhum
psycopg2: Nenhum
jinja2: 2.9.6
s3fs: Nenhum
pandas_gbq: Nenhum
pandas_datareader: Nenhum

Indexing

Comentários muito úteis

Encontrou o mesmo problema, teve dois pensamentos:

Armazenar um dict dentro de um DataFrame é incomum, mas há casos válidos em que o software pode estar usando Pandas como uma maneira de representar e manipular dados de estilo de chave/valor arbitrário onde os dados são indexados de uma maneira que faça sentido para a representação em painel.

O comportamento de que a indexação baseada em localização atualizará as colunas com base nas chaves/valores de um dicionário fornecido foi uma surpresa para mim. Este é um recurso de conveniência interessante que faz sentido quando uma coluna explícita não é referenciada. Por exemplo, ao fornecer:

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

Faz sentido que as chaves do dicionário possam ser escritas como colunas e que df.loc[row, key1] == value1 . No entanto, ao fornecer um índice de coluna explícito, inferir as colunas de destino de um dicionário fornecido é (para mim) contra-intuitivo. Se em vez disso eu fornecer:

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

Estou denotando explicitamente que quero armazenar o valor inteiro na coluna col e espero que o dicionário seja inserido como está.

De qualquer forma, concordo com @jreback que isso é um pouco não idiomático, MAS sou solidário com a questão original levantada por @andreas-thomik. Eu encontrei um problema em que tentar armazenar um dict em um elemento de um dataframe usando essa sintaxe fazia sentido para o problema específico que eu estava enfrentando, então ele não está totalmente sozinho com essa solicitação.

Todos 3 comentários

isso é bastante não-idiomático, e você está praticamente sozinho aqui. você poderia fazer isso apenas usando uma lista/tupla em torno dele

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

Encontrou o mesmo problema, teve dois pensamentos:

Armazenar um dict dentro de um DataFrame é incomum, mas há casos válidos em que o software pode estar usando Pandas como uma maneira de representar e manipular dados de estilo de chave/valor arbitrário onde os dados são indexados de uma maneira que faça sentido para a representação em painel.

O comportamento de que a indexação baseada em localização atualizará as colunas com base nas chaves/valores de um dicionário fornecido foi uma surpresa para mim. Este é um recurso de conveniência interessante que faz sentido quando uma coluna explícita não é referenciada. Por exemplo, ao fornecer:

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

Faz sentido que as chaves do dicionário possam ser escritas como colunas e que df.loc[row, key1] == value1 . No entanto, ao fornecer um índice de coluna explícito, inferir as colunas de destino de um dicionário fornecido é (para mim) contra-intuitivo. Se em vez disso eu fornecer:

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

Estou denotando explicitamente que quero armazenar o valor inteiro na coluna col e espero que o dicionário seja inserido como está.

De qualquer forma, concordo com @jreback que isso é um pouco não idiomático, MAS sou solidário com a questão original levantada por @andreas-thomik. Eu encontrei um problema em que tentar armazenar um dict em um elemento de um dataframe usando essa sintaxe fazia sentido para o problema específico que eu estava enfrentando, então ele não está totalmente sozinho com essa solicitação.

@aaclayton isso está relacionado a #18955 . Poderíamos/deveríamos suportar melhor a configuração de escalares de dicts (e outros iteráveis). É um pouco complicado embora.

Esta página foi útil?
0 / 5 - 0 avaliações