私はこのような辞書のリストを持っています:
[{'points': 50, 'time': '5:00', 'year': 2010},
{'points': 25, 'time': '6:00', 'month': "february"},
{'points':90, 'time': '9:00', 'month': 'january'},
{'points_h1':20, 'month': 'june'}]
そして私はこれをこのようなパンダDataFrame
に変えたいと思います:
month points points_h1 time year
0 NaN 50 NaN 5:00 2010
1 february 25 NaN 6:00 NaN
2 january 90 NaN 9:00 NaN
3 june NaN 20 NaN NaN
注:列の順序は関係ありません。
上記のように辞書のリストをパンダDataFrameに変換するにはどうすればよいですか?
単にd
をあなたの辞書のリストとすると、単に:
pd.DataFrame(d)
パンダ16.2では、これを機能させるためにpd.DataFrame.from_records(d)
をしなければなりませんでした。
辞書のリストをパンダDataFrameに変換するにはどうすればよいですか?
他の答えは正しいですが、これらの方法の利点と制限の点からはあまり説明されていません。この記事の目的は、さまざまな状況下でこれらのメソッドの例を示し、いつ使用するか(および使用しない場合)を検討し、代替案を提案することです。
DataFrame()
、 DataFrame.from_records()
、および .from_dict()
データの構造と形式によっては、3つの方法すべてがうまくいくか、あるいは他のものよりもうまくいくか、まったくうまくいかない場合があります。
非常に人為的な例を考えてみましょう。
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}]
このリストはすべてのキーが存在する「レコード」で構成されています。これはあなたが遭遇する可能性がある最も簡単なケースです。
# 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
orient='index'
/'columns'
先に進む前に、異なる種類の辞書の向きを区別し、パンダでサポートすることが重要です。 2つの主要なタイプがあります: "columns"と "index"です。
orient='columns'
「列」の向きを持つ辞書は、それらのキーが同等のDataFrame内の列に対応するようになります。
例えば、上のdata
は "columns"の向きです。
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
注:pd.DataFrame.from_records
を使用している場合、方向は「列」であると想定され(他には指定できません)、それに応じて辞書がロードされます。
orient='index'
この方向では、キーはインデックス値に対応すると見なされます。この種のデータは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
このケースはOPでは考慮されていませんが、知ることはまだ有用です。
結果のDataFrameにカスタムインデックスが必要な場合は、index=...
引数を使用してそれを設定できます。
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
これはpd.DataFrame.from_dict
ではサポートされていません。
欠けているキー/列の値を持つ辞書を処理するときには、すべてのメソッドはそのまま使用できます。例えば、
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
「すべての列を読みたくない場合はどうすればいいですか」。 columns=...
パラメータを使用してこれを簡単に指定できます。
たとえば、上のdata2
の辞書の例から、列「A」、「D」、および「F」のみを読みたい場合は、リストを渡すことによってそれを行うことができます。
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
これは、デフォルトの向き "columns"のpd.DataFrame.from_dict
ではサポートされていません。
pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError: cannot use columns parameter with orient='columns'
これらのメソッド直接ではサポートされていません。データを反復処理し、反復処理の際に 逆削除 in-placeを実行する必要があります。たとえば、0だけを抽出するには番目 と2nd 上記のdata2
からの行では、次のものを使用できます。
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
json_normalize
ネストしたデータ用上記の方法に代わる強力で堅牢な方法は、辞書のリスト(レコード)を処理するjson_normalize
関数です。さらに、入れ子になった辞書を処理することもできます。
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
繰り返しになりますが、json_normalize
に渡されるデータは辞書リスト(レコード)形式である必要があることに注意してください。
すでに述べたように、json_normalize
は入れ子になった辞書も処理できます。これはドキュメンテーションから取った例です。
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
meta
およびrecord_path
引数に関する詳細は、ドキュメントをチェックしてください。
サポートされている機能とともに、上記のすべてのメソッドの表があります。
pd.DataFrame.from_dict(d)
を次のように使うこともできます。
In [8]: d = [{'points': 50, 'time': '5:00', 'year': 2010},
...: {'points': 25, 'time': '6:00', 'month': "february"},
...: {'points':90, 'time': '9:00', 'month': 'january'},
...: {'points_h1':20, 'month': 'june'}]
In [12]: pd.DataFrame.from_dict(d)
Out[12]:
month points points_h1 time year
0 NaN 50.0 NaN 5:00 2010.0
1 february 25.0 NaN 6:00 NaN
2 january 90.0 NaN 9:00 NaN
3 june NaN 20.0 NaN NaN
何人かの人々がこれに出くわし、ここで何も役に立たないことを知っています。私が見つけた最も簡単な方法は次のとおりです。
dict_count = len(dict_list)
df = pd.DataFrame(dict_list[0], index=[0])
for i in range(1,dict_count-1):
df = df.append(dict_list[i], ignore_index=True)
これが誰かを助けることを願っています!