カテゴリー

Python基礎

【辞書&pandas】dict{name: , val: {a: [~], b:[~]}}のpandas化

2021年4月10日

多項式関数のグラフ

こんな人にオススメ


ネストされたdict配列をpandasDataFrameに変換したいんだけどどうしたらいい?

最近、以下のような、辞書の一部の中にさらに辞書の入っている形式の辞書をtxtファイルに保存する機会があった。その時に使用した辞書からpandasDataFrameへの変換方法について今回は紹介する。
import numpy as np
import pandas as pd
import sys

dct = {
    'name': 'name',
    # valがネストされている
    'val': {
        'a': [1, 2, 3],
        'b': [10, 20, 30],
    }
}

python環境は以下。

  • Python 3.9.2
  • numpy 1.20.1
  • pandas 1.2.3

運営者のメガネとです。YouTubeTwitterInstagramも運営中。

自己紹介はこちらから、お問い合わせはこちらからお願いいたします。

運営者メガネ

データの作成とDataFrame

まずは辞書型のデータを作成する。その後、その辞書をpandasDataFrameに変換する。

データ作成

今回は多項式を1つのxで作成し、多項式の部分をネストする形式とする。

# 最終データを入れる辞書を作成
data = {}

# 横軸
x = np.arange(-2, 2 + 0.01, 0.01)
data['x'] = x

# 縦軸

# 字数の英語名称
name = {
    1: 'linear',
    2: 'quadratic',
    3: 'cubic',
    4: 'quartic',
    5: 'quintic',
}

data['y'] = {}
for order in range(1, 6):
    data['y'][name[order]] = x ** order

dataから派生するkeyの一覧は以下の通り。

'x', 'y',
['y']['linear'], ['y']['quadratic'], 
['y']['cubic'], ['y']['quartic'], ['y']['quintic']

DataFrameに変換

前節で辞書型を作成したので、ここではpandasDataFrameに変換する。まずはそのままpd.DataFrameに入れる。しかしdataはネストの構造になっているのでそのままではエラー。

# 単純にDataFrameにする
# df0 = pd.DataFrame(data)
# ValueError: Mixing dicts with non-Series may lead to ambiguous ordering.

ではネスト部分だけ取り出したらどうかというとそれは可能。しかし、横軸を担うxの情報が消える。

# yだけにするとエラーは出ないが、xがない
df1 = pd.DataFrame(data['y'])
print(df1)
#      linear  quadratic     cubic    quartic    quintic
# 0     -2.00     4.0000 -8.000000  16.000000 -32.000000
# 1     -1.99     3.9601 -7.880599  15.682392 -31.207960
# 2     -1.98     3.9204 -7.762392  15.369536 -30.431682
# 3     -1.97     3.8809 -7.645373  15.061385 -29.670928
# 4     -1.96     3.8416 -7.529536  14.757891 -28.925465
# ..      ...        ...       ...        ...        ...
# 396    1.96     3.8416  7.529536  14.757891  28.925465
# 397    1.97     3.8809  7.645373  15.061385  29.670928
# 398    1.98     3.9204  7.762392  15.369536  30.431682
# 399    1.99     3.9601  7.880599  15.682392  31.207960
# 400    2.00     4.0000  8.000000  16.000000  32.000000

# [401 rows x 5 columns]

そこで、1つのDataFrameにするためにx部分とy部分を新たな辞書の中で展開してDataFrameにする。この場合はエラーが出ずにクリア。しかし、インデックスが「0 1 2 ...」のように行番号になっている。

# 辞書の中で展開して、xをDataFrameに入れる
df2 = pd.DataFrame({**{'x': data['x']}, **data['y']})
print(df2)
#         x  linear  quadratic     cubic    quartic    quintic
# 0   -2.00   -2.00     4.0000 -8.000000  16.000000 -32.000000
# 1   -1.99   -1.99     3.9601 -7.880599  15.682392 -31.207960
# 2   -1.98   -1.98     3.9204 -7.762392  15.369536 -30.431682
# 3   -1.97   -1.97     3.8809 -7.645373  15.061385 -29.670928
# 4   -1.96   -1.96     3.8416 -7.529536  14.757891 -28.925465
# ..    ...     ...        ...       ...        ...        ...
# 396  1.96    1.96     3.8416  7.529536  14.757891  28.925465
# 397  1.97    1.97     3.8809  7.645373  15.061385  29.670928
# 398  1.98    1.98     3.9204  7.762392  15.369536  30.431682
# 399  1.99    1.99     3.9601  7.880599  15.682392  31.207960
# 400  2.00    2.00     4.0000  8.000000  16.000000  32.000000

# [401 rows x 6 columns]

ということで、xがインデックスとなるように指定した。この場合はインデックスが行番号ではなくなるのでスッキリした見た目になる。

# indexはxであると指定
df3 = pd.DataFrame({**{'x': data['x']}, **data['y']}).set_index('x')
print(df3)
#        linear  quadratic     cubic    quartic    quintic
# x
# -2.00   -2.00     4.0000 -8.000000  16.000000 -32.000000
# -1.99   -1.99     3.9601 -7.880599  15.682392 -31.207960
# -1.98   -1.98     3.9204 -7.762392  15.369536 -30.431682
# -1.97   -1.97     3.8809 -7.645373  15.061385 -29.670928
# -1.96   -1.96     3.8416 -7.529536  14.757891 -28.925465
# ...       ...        ...       ...        ...        ...
#  1.96    1.96     3.8416  7.529536  14.757891  28.925465
#  1.97    1.97     3.8809  7.645373  15.061385  29.670928
#  1.98    1.98     3.9204  7.762392  15.369536  30.431682
#  1.99    1.99     3.9601  7.880599  15.682392  31.207960
#  2.00    2.00     4.0000  8.000000  16.000000  32.000000

# [401 rows x 5 columns]

データの書き込みと読み込み

前章で辞書をDataFrameに変換した。ここでは作成したDataFrameをtxtファイルに書き込み、そしてそのファイルを再度読み込む。

書き込み

前章で作成したDataFrameをtxtファイルに書き込む。まずはdf1df1はインデックスが行番号でかつ、xの情報が抜け落ちてしまっている。そのため、df1を使用する際にはxを別途指定しなければならない。

# yとインデックスの0, 1, 2, 3,...
df1.to_csv('dict_pandas1.txt', sep='\\t')

# 	linear	quadratic	cubic	quartic	quintic
# 0	-2.0	4.0	-8.0	16.0	-32.0
# 1	-1.99	3.9601	-7.880599	15.68239201	-31.2079600999
# 2	-1.98	3.9204	-7.762392	15.36953616	-30.431681596799997
# 3	-1.97	3.8809	-7.645372999999999	15.06138481	-29.670928075699997
# 4	-1.96	3.8415999999999997	-7.529535999999999	14.757890559999998	-28.925465497599998
# 5	-1.95	3.8024999999999998	-7.414874999999999	14.459006249999998	-28.195062187499996
# 6	-1.94	3.7636	-7.301384	14.164684959999999	-27.479488822399997
# 7	-1.93	3.7249	-7.189056999999999	13.874880009999998	-26.778518419299996
# 8	-1.92	3.6864	-7.077887999999999	13.589544959999998	-26.091926323199996

df2でもインデックスが行番号であるが、今回はxの情報も存在する。実際に使用する際にはxy、そしてインデックスの情報をうまく分けないといけない。

# x, yとインデックスの0, 1, 2, 3,...
df2.to_csv('dict_pandas2.txt', sep='\\t')
# 	x	linear	quadratic	cubic	quartic	quintic
# 0	-2.0	-2.0	4.0	-8.0	16.0	-32.0
# 1	-1.99	-1.99	3.9601	-7.880599	15.68239201	-31.2079600999
# 2	-1.98	-1.98	3.9204	-7.762392	15.36953616	-30.431681596799997
# 3	-1.97	-1.97	3.8809	-7.645372999999999	15.06138481	-29.670928075699997
# 4	-1.96	-1.96	3.8415999999999997	-7.529535999999999	14.757890559999998	-28.925465497599998
# 5	-1.95	-1.95	3.8024999999999998	-7.414874999999999	14.459006249999998	-28.195062187499996
# 6	-1.94	-1.94	3.7636	-7.301384	14.164684959999999	-27.479488822399997
# 7	-1.93	-1.93	3.7249	-7.189056999999999	13.874880009999998	-26.778518419299996
# 8	-1.92	-1.92	3.6864	-7.077887999999999	13.589544959999998	-26.091926323199996

df3の場合はインデックスがxになっているので、データを見たときに一番左にxがあるから横軸だなとわかりやすい。しかし、txtファイルにした時点でDataFrameのインデックスとしての機能はなくなっているので、読み込むときはインデックスの指定をしなければいけない。

# xをインデックスにしたy
df3.to_csv('dict_pandas3.txt', sep='\\t')
# x	linear	quadratic	cubic	quartic	quintic
# -2.0	-2.0	4.0	-8.0	16.0	-32.0
# -1.99	-1.99	3.9601	-7.880599	15.68239201	-31.2079600999
# -1.98	-1.98	3.9204	-7.762392	15.36953616	-30.431681596799997
# -1.97	-1.97	3.8809	-7.645372999999999	15.06138481	-29.670928075699997
# -1.96	-1.96	3.8415999999999997	-7.529535999999999	14.757890559999998	-28.925465497599998
# -1.95	-1.95	3.8024999999999998	-7.414874999999999	14.459006249999998	-28.195062187499996
# -1.94	-1.94	3.7636	-7.301384	14.164684959999999	-27.479488822399997
# -1.93	-1.93	3.7249	-7.189056999999999	13.874880009999998	-26.778518419299996
# -1.92	-1.92	3.6864	-7.077887999999999	13.589544959999998	-26.091926323199996

また、df3で書き込み時にindexを指定したとしてもtxtファイル上では何も変化はない。

# xをインデックスにしたy。xをindex指定しても上記とは変わらない
df3.to_csv('dict_pandas3_2.txt', sep='\\t', index='x')
# x	linear	quadratic	cubic	quartic	quintic
# -2.0	-2.0	4.0	-8.0	16.0	-32.0
# -1.99	-1.99	3.9601	-7.880599	15.68239201	-31.2079600999
# -1.98	-1.98	3.9204	-7.762392	15.36953616	-30.431681596799997
# -1.97	-1.97	3.8809	-7.645372999999999	15.06138481	-29.670928075699997
# -1.96	-1.96	3.8415999999999997	-7.529535999999999	14.757890559999998	-28.925465497599998
# -1.95	-1.95	3.8024999999999998	-7.414874999999999	14.459006249999998	-28.195062187499996
# -1.94	-1.94	3.7636	-7.301384	14.164684959999999	-27.479488822399997
# -1.93	-1.93	3.7249	-7.189056999999999	13.874880009999998	-26.778518419299996
# -1.92	-1.92	3.6864	-7.077887999999999	13.589544959999998	-26.091926323199996

データの読み込み

データの読み込みに関しては、df2df3の場合で解説する。まずはdf2。この場合はxと行番号が両立しているので行番号を使用せず、xをインデックスとするように指定する。

# 使用するインデックスはxと各他国式の列なので、1-6列目を使用
# インデックスにする列はそのうちの0列目に該当
df_read2 = pd.read_csv(
    'dict_pandas2.txt', sep='\\t', index_col=0,
    usecols=[1, 2, 3, 4, 5, 6],
)
print(df_read2)
#        linear  quadratic     cubic    quartic    quintic
# x
# -2.00   -2.00     4.0000 -8.000000  16.000000 -32.000000
# -1.99   -1.99     3.9601 -7.880599  15.682392 -31.207960
# -1.98   -1.98     3.9204 -7.762392  15.369536 -30.431682
# -1.97   -1.97     3.8809 -7.645373  15.061385 -29.670928
# -1.96   -1.96     3.8416 -7.529536  14.757891 -28.925465
# ...       ...        ...       ...        ...        ...
#  1.96    1.96     3.8416  7.529536  14.757891  28.925465
#  1.97    1.97     3.8809  7.645373  15.061385  29.670928
#  1.98    1.98     3.9204  7.762392  15.369536  30.431682
#  1.99    1.99     3.9601  7.880599  15.682392  31.207960
#  2.00    2.00     4.0000  8.000000  16.000000  32.000000

# [401 rows x 5 columns]

一方で、df3はインデックスがすでにxの状態で出力したので、インデックスの位置を指定するだけ。

# インデックスに使用するのは0列目のx
df_read3 = pd.read_csv('dict_pandas3.txt', sep='\\t', index_col=0,)
print(df_read3)
#        linear  quadratic     cubic    quartic    quintic
# x
# -2.00   -2.00     4.0000 -8.000000  16.000000 -32.000000
# -1.99   -1.99     3.9601 -7.880599  15.682392 -31.207960
# -1.98   -1.98     3.9204 -7.762392  15.369536 -30.431682
# -1.97   -1.97     3.8809 -7.645373  15.061385 -29.670928
# -1.96   -1.96     3.8416 -7.529536  14.757891 -28.925465
# ...       ...        ...       ...        ...        ...
#  1.96    1.96     3.8416  7.529536  14.757891  28.925465
#  1.97    1.97     3.8809  7.645373  15.061385  29.670928
#  1.98    1.98     3.9204  7.762392  15.369536  30.431682
#  1.99    1.99     3.9601  7.880599  15.682392  31.207960
#  2.00    2.00     4.0000  8.000000  16.000000  32.000000

# [401 rows x 5 columns]

グラフ化


最後に読み込んだデータをグラフ化する。グラフ化する方法は下記記事に書いている、即席plotlyのコードで行う。

【随時更新 備忘録】plotlyのグラフ即席作成コード

こんな人にオススメ plotlyって{ ...

続きを見る

即席コードのあるディレクトリは2つ親なので、sys.path.apped('../../')で階層を登っている。また、ファイル名はplotly_layout_template.py

sys.path.append('../../')
import plotly_layout_template as template

# グラフ化用にデータ整形
lst = []
for name, val in df_read3.items():
    print(name)
    dct = {'x': df_read3.index, 'y': val.values, 'name': name}
    lst.append(dct)

# グラフ化
template.graph(
    data=lst,
    title='polynominal',
    xtitle='x',
    ytitle='y',
    pic=True,
    save=True,
    filename='dict_pandas',
)

便利にすると複雑化

今回はyがネストされた辞書をpandasDataFrameに変換し、書き込み・読み込み・グラフ化を行なった。

ネストさせることでデータ構造的にはわかりやすくはなるが扱うのが難しくなる。色々なアプローチ方法があるのでみなさま個人で最適と思われる方法を見つけてほしい。

plt

【plt&pandas】df.plot()でmatplotlibのグラフを作成

2022/8/19

こんな人にオススメ pandasのデ} ...

Python基礎

【Python&Excel】openpyxlでフォルダ内の複数csv→1つのExcelへ

2022/8/19

こんな人にオススメ 複数のcsv ...

Pythonでの比較

【plotly&pandas】df.plot()でPlotlyのグラフを作成

2022/8/19

こんな人にオススメ pnadasのデ} ...

pandas

【python&Excel】pandasでエクセルファイルを読み込み・書き出し

2022/8/19

こんな人にオススメ pandasを使ī ...

スイッチボット

2022/11/28

【SwitchBotロックレビュー】これからのスタンダードになりうるスマートロック

こんな人にオススメ SwitchBotからスマートロック「SwitchBotロック」が発売された ...

生活に役立つ

2022/11/28

【メガネ厳選】クソ便利に使っているサービスやアイテム達

このページでは執筆者「メガネ」が実際に使って便利だと感じているサ ...

マウス

2022/9/11

【Logicool MX ERGO vs MX Master 3】ERGOをメインにした決定的な理由

こんな疑問・お悩みを持っている人におすすめ 執筆者はLogicoolのハイエンӠ ...

完全ワイヤレスイヤホン(TWS)

2022/11/21

【ながら聴きイヤホン比較】SONY LinkBuds、ambie、BoCoはどれがおすすめ?

こんな人におすすめ 耳を塞がない開放型のイヤホンに完全ワイヤレスӟ ...

macOSアプリケーション

2022/10/15

【M1 Mac】MacBook Proに入れている便利でニッチなアプリを21個紹介する

こんな人におすすめ MacBookを購入してLINEとか必要最低限のアプリは入れた。 ...

完全ワイヤレスイヤホン(TWS)

2022/10/23

【SENNHEISER MOMENTUM True Wireless 3レビュー】高レベルでバランス型の高音質イヤホン

こんな人におすすめ SENNHEISER MOMENTUM True Wireless 3って実際のところどうなの? 評判は良い ...

完全ワイヤレスイヤホン(TWS)

2022/11/21

【SONY WF-1000XM4レビュー】神とゴミのハーフ&ハーフ

こんな人におすすめ SONYのフラグシップモデル「SONY WF-1000XM4」ってどれくらい性 ...

完全ワイヤレスイヤホン(TWS)

2022/8/19

【Nothing ear (1)レビュー】ライトな完成度、アップデートに期待

こんな人にオススメ 完全ワイヤレスイヤホン(TWS)でスケルトンボディ ...

Pythonを学びたいけど独学できる時間なんてない人へのすゝめ

執筆者は大学の研究室・大学院にて独学でPythonを習得した。

でも社会人になったら独学で行うには時間も体力もなくて大変だ。

時間がない社会人だからこそプロの教えを乞うのが効率的。

ここでは色んなタイプに合ったプログラミングスクールの紹介をする。

  • この記事を書いた人

メガネ

ベンチャー企業のWebエンジニア駆け出し。独学のPythonで天文学系の大学院を修了→新卒を1.5年で辞める→転職→今に至る。
常時金欠のガジェット好きでM1 MacBook Pro x Galaxy S22 Ultraの狂人。
人見知りで根暗だったけど、人生楽しもうと思って良い方向に狂う→人生が楽しい

ガジェットのレビューとPythonコードを記事にしています。ぜひ楽しんでください🦊
自己紹介と半生→変わって楽しいの繰り返し

-Python基礎
-, ,