カテゴリー

当サイトはアフィリエイトプログラムによる収益を得ています〈景品表示法に基づく表記です)

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のグラフ即席作成コード

続きを見る

即席コードのあるディレクトリは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を使用してc ...

ガジェット

2023/9/18

【デスクツアー2022下半期】モノは少なく、でも効率的に Desk Updating #0

今回はガジェットブロガーなのにデスク環境を構築していない執筆者の ...

ライフハック

2023/9/16

【Audible vs YouTube Premium】耳で聴く音声学習コンテンツを比較

ワイヤレスイヤホンが普及し耳で学習することへのハードルが格段に下 ...

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

2023/9/18

【SENNHEISER MOMENTUM True Wireless 3レビュー】全てが整ったイヤホン

今回は高音質・高機能なSENNHEISERのフラグシップ完全ワイヤレスイヤホン「SENNH ...

ライフハック

2023/3/11

【YouTube Premiumとは】メリットしかないから全員入れ

今回はYouTube Premiumを実際に使ってみてどうなのか、どんなメリット/デメリット ...

マウス

2023/8/17

【Logicool MX ERGOレビュー】疲れない作業効率重視トラックボールマウス

こんな人におすすめ トラックボールマウスの王道Logicool MX ERGOが気になるけどऩ ...

ベストバイ

2023/9/18

【ベストバイ2022】今年買って良かったモノのトップ10

2022年ベストバイ この1年を振り返って執筆者は何を買ったのか。ガジェッ& ...

スマホ

2023/1/15

【楽天モバイル×povo2.0の併用】月1,000円の保険付きデュアルSIM運用

こんな人におすすめ 楽天モバイルとpovo2.0のデュアルSIM運用って実際のとこ ...

マウス

2023/9/16

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

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

macOSアプリケーション

2022/9/30

【Chrome拡張機能】便利で効率的に作業できるおすすめの拡張機能を18個紹介する

こんな人におすすめ Chromeの拡張機能を入れたいけど、調べても同じような ...

macOSアプリケーション

2023/5/3

【Automator活用術】Macで生産性を上げる作業の自動化術

今回はMacに標準でインストールされているアプリ「Automator」を使ってできる ...

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

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

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

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

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

  • この記事を書いた人

メガネ

Webエンジニア駆け出し。独学のPythonで天文学系の大学院を修了。常時金欠のガジェット好きでM2 Pro MacBook Pro(30万円) x Galaxy S22 Ultra(17万円)使いの狂人。自己紹介と半生→変わって楽しいの繰り返しレビュー依頼など→お問い合わせ運営者情報、TwitterX@m_ten_pa、 YouTube@megatenpa、 Threads@megatenpa

-Python基礎
-, ,