Como converter uma lista de dicionários em um DataFrame do pandas?
As outras respostas estão corretas, mas pouco foi explicado em termos de vantagens e limitações desses métodos. O objetivo deste post será mostrar exemplos desses métodos em diferentes situações, discutir quando usar (e quando não usar) e sugerir alternativas.
Dependendo da estrutura e formato dos seus dados, há situações em que todos os três métodos funcionam, ou alguns funcionam melhor que outros, ou alguns não funcionam.
Considere um exemplo muito artificial.
np.random.seed(0)
data = pd.DataFrame(
np.random.choice(10, (3, 4)), columns=list('ABCD')).to_dict('r')
print(data)
[{'A': 5, 'B': 0, 'C': 3, 'D': 3},
{'A': 7, 'B': 9, 'C': 3, 'D': 5},
{'A': 2, 'B': 4, 'C': 7, 'D': 6}]
Esta lista consiste em "registros" com todas as chaves presentes. Este é o caso mais simples que você pode encontrar.
# The following methods all produce the same output.
pd.DataFrame(data)
pd.DataFrame.from_dict(data)
pd.DataFrame.from_records(data)
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
Palavra no dicionário Orientações: orient='index'
/'columns'
Antes de continuar, é importante fazer a distinção entre os diferentes tipos de orientações do dicionário e apoiar com os pandas. Existem dois tipos principais: "colunas" e "índice".
orient='columns'
Dicionários com a orientação "colunas" terão suas chaves correspondentes a colunas no DataFrame equivalente.
Por exemplo, data
acima está no oriente "colunas".
data_c = [
{'A': 5, 'B': 0, 'C': 3, 'D': 3},
{'A': 7, 'B': 9, 'C': 3, 'D': 5},
{'A': 2, 'B': 4, 'C': 7, 'D': 6}]
pd.DataFrame.from_dict(data_c, orient='columns')
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
Nota: Se você estiver usando pd.DataFrame.from_records
, a orientação será assumida como "colunas" (você não pode especificar o contrário) e os dicionários serão carregados de acordo.
orient='index'
Nesse sentido, presume-se que as chaves correspondam aos valores do índice. Esse tipo de dados é mais adequado pd.DataFrame.from_dict
.
data_i ={
0: {'A': 5, 'B': 0, 'C': 3, 'D': 3},
1: {'A': 7, 'B': 9, 'C': 3, 'D': 5},
2: {'A': 2, 'B': 4, 'C': 7, 'D': 6}}
pd.DataFrame.from_dict(data_i, orient='index')
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
Esse caso não é considerado no OP, mas ainda é útil saber.
Definir índice personalizado
Se você precisar de um índice personalizado no DataFrame resultante, poderá configurá-lo usando o index=...
argumento
pd.DataFrame(data, index=['a', 'b', 'c'])
# pd.DataFrame.from_records(data, index=['a', 'b', 'c'])
A B C D
a 5 0 3 3
b 7 9 3 5
c 2 4 7 6
Isso não é suportado por pd.DataFrame.from_dict
.
Lidando com chaves / colunas ausentes
Todos os métodos funcionam imediatamente ao manipular dicionários com valores de chaves / colunas ausentes. Por exemplo,
data2 = [
{'A': 5, 'C': 3, 'D': 3},
{'A': 7, 'B': 9, 'F': 5},
{'B': 4, 'C': 7, 'E': 6}]
# The methods below all produce the same output.
pd.DataFrame(data2)
pd.DataFrame.from_dict(data2)
pd.DataFrame.from_records(data2)
A B C D E F
0 5.0 NaN 3.0 3.0 NaN NaN
1 7.0 9.0 NaN NaN NaN 5.0
2 NaN 4.0 7.0 NaN 6.0 NaN
Subconjunto de colunas de leitura
"E se eu não quiser ler em todas as colunas"? Você pode especificar isso facilmente usando o columns=...
parâmetro
Por exemplo, no dicionário de exemplo data2
acima, se você quiser ler apenas as colunas "A ',' D 'e' F ', poderá fazê-lo passando uma lista:
pd.DataFrame(data2, columns=['A', 'D', 'F'])
# pd.DataFrame.from_records(data2, columns=['A', 'D', 'F'])
A D F
0 5.0 3.0 NaN
1 7.0 NaN 5.0
2 NaN NaN NaN
Isso não é suportado pelas pd.DataFrame.from_dict
"colunas" orientais padrão.
pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError: cannot use columns parameter with orient='columns'
Subconjunto de linhas de leitura
Não é suportado por nenhum desses métodos diretamente . Você precisará iterar sobre seus dados e executar uma exclusão reversa no local enquanto itera. Por exemplo, para extrair apenas a 0 º e 2 nd linhas de data2
acima, você pode usar:
rows_to_select = {0, 2}
for i in reversed(range(len(data2))):
if i not in rows_to_select:
del data2[i]
pd.DataFrame(data2)
# pd.DataFrame.from_dict(data2)
# pd.DataFrame.from_records(data2)
A B C D E
0 5.0 NaN 3 3.0 NaN
1 NaN 4.0 7 NaN 6.0
Panaceia: json_normalize
para dados aninhados
Uma alternativa forte e robusta aos métodos descritos acima é a json_normalize
função que trabalha com listas de dicionários (registros) e, além disso, também pode lidar com dicionários aninhados.
pd.io.json.json_normalize(data)
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
pd.io.json.json_normalize(data2)
A B C D E
0 5.0 NaN 3 3.0 NaN
1 NaN 4.0 7 NaN 6.0
Novamente, lembre-se de que os dados transmitidos json_normalize
precisam estar no formato de lista de dicionários (registros).
Como mencionado, json_normalize
também pode manipular dicionários aninhados. Aqui está um exemplo retirado da documentação.
data_nested = [
{'counties': [{'name': 'Dade', 'population': 12345},
{'name': 'Broward', 'population': 40000},
{'name': 'Palm Beach', 'population': 60000}],
'info': {'governor': 'Rick Scott'},
'shortname': 'FL',
'state': 'Florida'},
{'counties': [{'name': 'Summit', 'population': 1234},
{'name': 'Cuyahoga', 'population': 1337}],
'info': {'governor': 'John Kasich'},
'shortname': 'OH',
'state': 'Ohio'}
]
pd.io.json.json_normalize(data_nested,
record_path='counties',
meta=['state', 'shortname', ['info', 'governor']])
name population state shortname info.governor
0 Dade 12345 Florida FL Rick Scott
1 Broward 40000 Florida FL Rick Scott
2 Palm Beach 60000 Florida FL Rick Scott
3 Summit 1234 Ohio OH John Kasich
4 Cuyahoga 1337 Ohio OH John Kasich
Para mais informações sobre os argumentos meta
e record_path
, consulte a documentação.
Resumindo
Aqui está uma tabela de todos os métodos discutidos acima, juntamente com os recursos / funcionalidades suportados.
* Use orient='columns'
e transponha para obter o mesmo efeito que orient='index'
.