辞書のリストをpandas DataFrameに変換する


657

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

[{'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

注:列の順序は関係ありません。

上記のように、辞書のリストをpandas DataFrameに変換するにはどうすればよいですか?

回答:


951

仮にはd単に、dictsのリストです:

pd.DataFrame(d)

3
キー/値のペアの1つをインデックス(例:時間)としてどのように使用できますか?
CatsLoveJazz

6
あなただけ行うことができます@CatsLoveJazz df = df.set_index('time')その後
ヨリス・

1
@CatsLoveJazzいいえ、dictから変換する場合は不可能です。
joris

6
パンダ0.19.2時点、ドキュメントのこのについての言及は、少なくともではないため、ドキュメントに、ありませんpandas.DataFrame
レオAlekseyev

1
ネストされた辞書の'{"":{"...場合はjson_normalizeアプローチを使用することに注意してください。@ cs95の詳細な回答を参照してください
ローレンツ

136

辞書のリストをpandas 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つの主要なタイプがあります。

orient='columns'
「列」方向のディクショナリのキーは、対応するDataFrameの列に対応します。

たとえば、data上記は「列」オリエントです。

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

これはpd.DataFrame.from_dict、デフォルトの方向「列」ではサポートされていません。

pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])

ValueError: cannot use columns parameter with orient='columns'

行のサブセットの読み取り

これらのメソッドでは直接サポートされていません。データを繰り返し処理し、繰り返し処理しながら逆方向の削除を実行する必要があります。たとえば、上から0 番目と2 番目の行のみを抽出するには、次の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

metarecord_path引数の詳細については、ドキュメントをご覧ください。


まとめ

サポートされている機能/機能とともに、上記で説明したすべての方法の表を以下に示します。

ここに画像の説明を入力してください

*を使用orient='columns'してから転置すると、と同じ効果が得られorient='index'ます。


8
わあ!さて、これはマージのSO投稿とともにAPIに属しています。まだ行っていない場合は、pandasのドキュメントに貢献してください。Ted Petrou は、パンダの人気に関するLinkedInの記事をStack Overflowに投稿したばかりで、優れたドキュメントの欠如がここでの質問の数の原因となっていると述べています。
スコットボストン

2
@ScottBoston正解です。今よりも真剣に検討する必要があることを知ったので、何度も聞いたことがあります。ドキュメンテーションは、同じ聴衆のほんの一部にしか届かない質問に投稿するよりも、ユーザーを助ける優れた方法になると思います。
cs95 2018

1
それはいい答えです。最新のパンダバージョンの下で、これらのよくある質問を再
検討するときがきたと思い

3
@ely:とにかく、ここに回答を書かない理由にはなりませどんな答えでも時代遅れになる可能性があります。それが私たちが投票しているものであり、ここには異なる視点と異なる目標が存在し、同じことを異なる方法で説明することは常に価値があります。
Martijn Pieters

1
@MartijnPieters私はあなたの最後の主張に質問し、同意しませんが、全体的に私はあなたに同意します。特に、いくつかの回答が更新または他の回答に基づく条件付きの違いである場合、同じ質問に対する異なる回答を一緒に照合することは、常に付加価値があるとは限りません。最悪の場合、これらの回答は、照合されたときに破壊的な値になる可能性があります(より古い回答をより正確な状態に編集するために最新の回答を使用するのとは対照的に)。しかし、繰り返しますが、私はおおむね同意します。
e

83

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


1
このアプローチの良いところは、それがまた機能することですdeque
MBZ

3
0.17.1@jorisソリューションを使用してパンダで正常に動作します
Anton Protopopov

2
Usinig 0.14.1と@jorisのソリューションは機能しませんでしたが、機能しました
mchen

13
では0.18.1from_recordsすべての辞書に同じキーがない場合に使用する必要があります。
fredcallaway 2016年

23

次のように使用することもできます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ない単一から、sのdictあなたがあなたの答えで想定通り。
a_guest 2017

@a_guest更新された回答を確認してください。私は想定していません。
shivsn 2017

2

何人かの人々がこれに遭遇し、ここで何も役に立たないことに気づくでしょう。私がそれを行うために見つけた最も簡単な方法は次のとおりです:

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)

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


1
list=[{'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'}]

そして単純な呼び出し:

pd=DataFrame.from_dict(list, orient='columns', dtype=None)

print(pd)

0

Pyhton3: 前述のソリューションのほとんどが機能します。ただし、データフレームのrow_numberが不要で、各行(レコード)を個別に書き込む必要がある場合があります。

その場合、以下の方法が便利です。

import csv

my file= 'C:\Users\John\Desktop\export_dataframe.csv'

records_to_save = data2 #used as in the thread. 


colnames = list[records_to_save[0].keys()] 
# remember colnames is a list of all keys. All values are written corresponding
# to the keys and "None" is specified in case of missing value 

with open(myfile, 'w', newline="",encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(colnames)
    for d in records_to_save:
        writer.writerow([d.get(r, "None") for r in colnames])

0

辞書のリストをpandas DataFrameに変換するには、「追加」を使用できます。

我々は持っていると呼ばれる辞書dicとDICは30個のリストアイテムを持っています(list1list2、...、 list30

  1. STEP1:あなたの結果を維持するための変数を定義します(例:total_df
  2. STEP2:初期化total_dfしてlist1
  3. ステップ3:すべてのリストを追加するために「ループ」を使用する total_df
total_df=list1
nums=Series(np.arange(start=2, stop=31))
for num in nums:
    total_df=total_df.append(dic['list'+str(num)])

詳細な2歳の回答で、@ cs95によって概説アプローチの上にこのアプローチの利点は何ですかDataFrame()DataFrame.from_records().from_dict()
Jeremy Caney

上記のすべてのメソッドを30個のリストを持つディクショナリに対してテストしましたが、Append関数を使用してのみ回答を得ました。
Armin Ahmadi Nasab
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.