/ / Pandas - substituem todos os valores NaN no DataFrame por objetos dict python vazios - python, pandas

Pandas - substitua todos os valores NaN no DataFrame por objetos dict python vazios - python, pandas

Eu tenho um DataFrame pandas onde cada célula contém um dict Python.

>>> data = {"Q":{"X":{2:2010}, "Y":{2:2011, 3:2009}},"R":{"X":{1:2013}}}
>>> frame = DataFrame(data)
>>> frame
Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        NaN

Eu gostaria de substituir o NaN com um dict vazio, para obter este resultado:

                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        {}

No entanto, porque o fillna A função interpreta empty dict não como um valor escalar, mas como um mapeamento de column -> value, não faz NADA se eu simplesmente fizer isso (ou seja, não funciona):

>>> frame.fillna(inplace=True, value={})
Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}        NaN

Existe alguma maneira de usar fillna para realizar o que eu quero? Eu tenho que percorrer todo o DataFrame ou construir um dict bobo com todas as minhas colunas mapeadas para empty dict?

Respostas:

5 para resposta № 1

Consegui usar DataFrame.applymap nesse caminho:

>>> from pandas import isnull
>>> frame=frame.applymap(lambda x: {} if isnull(x) else x)
>>> frame
Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}

Esta solução evita as armadilhas em ambosSolução de EdChum (onde todas as células NaN acabam apontando para o mesmo objeto dict subjacente na memória, evitando que sejam atualizadas independentemente umas das outras) e Shashank (onde uma estrutura de dados potencialmente grande precisa ser construída com dicts aninhados, apenas para especificar um único valor de dit vazio).


2 para resposta № 2

O problema é que quando um dict é passado para fillna, ele tenta preencher os valores com base nas colunas no quadro. Então a primeira solução que tentei foi -

frame.fillna({column: {} for column in frame.columns})

Mas se um dicionário é fornecido no segundo nível como este, ele tenta combinar as chaves com o índice, então a solução que funcionou foi -

frame.fillna({column: {ind: {} for ind in frame.index} for column in frame.columns})

Que dá -

                    Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}

A resposta do EdChum provavelmente é melhor para as suas necessidades, mas isso pode ser usado quando você não quer fazer alterações no lugar.

EDIT: A solução acima funciona bem para quadros menores, mas pode ser um problema para quadros maiores. Usando replace pode resolver isso.

frame.replace(np.nan, {column: {} for column in frame.columns})

1 para resposta № 3

Isso funciona usando loc:

In [6]:

frame.loc[frame["R"].isnull(), "R"] = {}
frame
Out[6]:
Q          R
X           {2: 2010}  {1: 2013}
Y  {2: 2011, 3: 2009}         {}

0 para a resposta № 4

Usar .values acessor para atribuir em matriz numpy diretamente:

frame.R = frame.R.astype(object)  # assertion

frame.R.values[frame.R.isnull()] = {}