Tenho dados salvos em um banco de dados postgreSQL. Estou consultando esses dados usando Python2.7 e transformando-os em um DataFrame do Pandas. No entanto, a última coluna desse quadro de dados possui um dicionário (ou lista?) De valores. O DataFrame fica assim:
[1] df
Station ID Pollutants
8809 {"a": "46", "b": "3", "c": "12"}
8810 {"a": "36", "b": "5", "c": "8"}
8811 {"b": "2", "c": "7"}
8812 {"c": "11"}
8813 {"a": "82", "c": "15"}
Eu preciso dividir esta coluna em colunas separadas para que o DataFrame fique assim:
[2] df2
Station ID a b c
8809 46 3 12
8810 36 5 8
8811 NaN 2 7
8812 NaN NaN 11
8813 82 NaN 15
O principal problema que estou enfrentando é que as listas não são do mesmo tamanho. Mas todas as listas contêm apenas os mesmos três valores: a, bec. E eles sempre aparecem na mesma ordem (um primeiro, b segundo, c terceiro).
O código a seguir USADO para trabalhar e retornar exatamente o que eu queria (df2).
[3] df
[4] objs = [df, pandas.DataFrame(df['Pollutant Levels'].tolist()).iloc[:, :3]]
[5] df2 = pandas.concat(objs, axis=1).drop('Pollutant Levels', axis=1)
[6] print(df2)
Eu estava executando esse código apenas na semana passada e estava funcionando bem. Mas agora meu código está quebrado e recebo esse erro da linha [4]:
IndexError: out-of-bounds on slice (end)
Não fiz alterações no código, mas agora estou recebendo o erro. Sinto que isso se deve ao fato de meu método não ser robusto ou adequado.
Qualquer sugestão ou orientação sobre como dividir esta coluna de listas em colunas separadas seria super apreciada!
EDIT: Eu acho que os métodos .tolist () e .apply não estão funcionando no meu código porque é uma string unicode, ou seja:
#My data format
u{'a': '1', 'b': '2', 'c': '3'}
#and not
{u'a': '1', u'b': '2', u'c': '3'}
Os dados estão sendo importados do banco de dados postgreSQL neste formato. Alguma ajuda ou idéias para esse problema? existe uma maneira de converter o unicode?
fonte
iloc
parteiloc[:, :3]
pressupõe que haverá 3 itens e talvez as fatias de dados mais recentes tenham apenas 1 ou 2 (por exemplo, por exemplo, não háb
comoindex 8813
).Respostas:
Para converter a string em um ditado real, você pode fazer
df['Pollutant Levels'].map(eval)
. Posteriormente, a solução abaixo pode ser usada para converter o ditado em colunas diferentes.Usando um pequeno exemplo, você pode usar
.apply(pd.Series)
:Para combiná-lo com o restante do quadro de dados, você pode
concat
outras colunas com o resultado acima:Usando seu código, isso também funciona se eu deixar de fora a
iloc
parte:fonte
pd.DataFrame(df[col].tolist())
há muito tempo, nunca pensei nissoapply(pd.Series)
. Muito agradável.DataFrame(df['col'].tolist())
abordagem é bem mais rápida que a abordagem de aplicação!df[col].map(eval)
antes de convertê-lo para uma trama de dadosEu sei que a pergunta é bastante antiga, mas cheguei aqui procurando respostas. Atualmente, existe uma maneira melhor (e mais rápida) de fazer isso usando
json_normalize
:Isso evita funções caras de aplicação ...
fonte
.json
arquivos são provenientes de fontes diferentes e nem sempre são as mesmas colunas aninhadas. Eu tenho tentado encontrar uma maneira de criar uma lista de colunas que contêm ditados, mas não consigo resolver issofrom pandas.io.json import json_normalize
meta_prefix
erecord_prefix
. Embora eu não possa fazer isso funcionar com meu dataframe (o dataframe final está correto no meu caso, mas gostaria de aplicar os prefixos).Tente o seguinte: Os dados retornados do SQL devem ser convertidos em um Dict. ou poderia ser
"Pollutant Levels"
agoraPollutants'
fonte
A resposta de Merlin é melhor e super fácil, mas não precisamos de uma função lambda. A avaliação do dicionário pode ser ignorada com segurança por uma das duas maneiras a seguir, conforme ilustrado abaixo:
Caminho 1: dois passos
Caminho 2: As duas etapas acima podem ser combinadas de uma só vez:
fonte
Eu recomendo fortemente que o método extraia a coluna 'Poluentes':
df_pollutants = pd.DataFrame(df['Pollutants'].values.tolist(), index=df.index)
é muito mais rápido que
df_pollutants = df['Pollutants'].apply(pd.Series)
quando o tamanho de df é gigante.
fonte
apply
todo o quadro de dados, é gerenciado por pandas, mas quando se tratavalues
dele, ele brinca apenas com onumpy ndarrays
que é intrinsecamente mais rápido, devido ao fato de terc
implementações puras .Você pode usar
join
compop
+tolist
. O desempenho é comparável aoconcat
comdrop
+tolist
, mas alguns podem encontrar este limpador de sintaxe:Benchmarking com outros métodos:
fonte
Uma solução de linha é a seguinte:
fonte
my_df = pd.DataFrame.from_dict(my_dict, orient='index', columns=['my_col'])
.. teria analisado o dict corretamente (colocando cada chave de dict em uma coluna df separada e valores de chave em linhas df), para que os dict não fossem compactados em uma única coluna em primeiro lugar.
fonte
Concatenei essas etapas em um método, você deve passar apenas o dataframe e a coluna que contém o comando para expandir:
fonte
fonte