web-dev-qa-db-ja.com

辞書のリストをパンダに変換するDataFrame

私はこのような辞書のリストを持っています:

[{'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に変換するにはどうすればよいですか?

435
appleLover

単にdをあなたの辞書のリストとすると、単に:

pd.DataFrame(d)
657
joris

パンダ16.2では、これを機能させるためにpd.DataFrame.from_records(d)をしなければなりませんでした。

67
szeitlin

辞書のリストをパンダ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引数に関する詳細は、ドキュメントをチェックしてください。


要約

サポートされている機能とともに、上記のすべてのメソッドの表があります。

enter image description here

41
cs95

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
18
shivsn

何人かの人々がこれに出くわし、ここで何も役に立たないことを知っています。私が見つけた最も簡単な方法は次のとおりです。

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)

これが誰かを助けることを願っています!

0
scottapotamus