Pythonでの家計簿の作り方

2020年11月29日プログラミング,家計Matplotlib,numpy,pandas,Python,家計簿

どうも、Econです。

Pythonで家計簿!エクセル家計簿からの移行

この記事でエクセル家計簿からPython管理に移行していると書きましたが、そもそも「エクセルからPythonでグラフ化する方法がわからない」と質問をいただきました。

なので、備忘も兼ねて実際のデータとコードを用いて方法を書いてみます。
この記事で使っているデータは下のリンクから自由にダウンロード、コードは直接コピペしてくださってOKです。

Example

全体の流れ

  1. エクセルのリストに月日と費目と金額を入力
  2. Pythonでグラフ化するために1ヶ月毎に集計した別表を準備する
  3. コードを書きグラフ化する

の3ステップで、それぞれで使うテーブルとアウトプットのイメージは下の通りです。

では、順番に見ていきます。

エクセルのリストに月日と費目と金額を入力

月日、費目、金額、何に使ったかのメモ欄くらいのシンプルなリストです。
費目は任意で設定できます。

Pythonでグラフ化するために別表を準備する

1のリストのままではPythonでグラフ化することは難しいので、集計用のテーブルを用意して、毎月の費目ごとの合計を集計します。

1のリストからfor文などを使って一気に3にいくこともできると思いますが、エクセルで表を準備したほうが楽なので、私はエクセルで準備しています。

使う関数もsumifs関数くらいなのでファイルサイズが膨らむこともありません。

コードを書きグラフ化する

まずコード全文を載せておきます。
なお、このコードはJupyterLabで動かす前提で書いているため、初行に%matplotinlineを書いていますが、不要ならこれは削除してください。

こちらがコード全文です。

#必要なライブラリをインポート
%matplotinline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

#データフレームを定義
df = pd.read_excel('Example.xlsx', sheet_name='DataFrame')
df.set_index('Date', inplace=True)
df['Saving'] = df['Income'] - df['Cost']
df = df.T

#グラフ化
fig, ax = plt.subplots(figsize=(15, 6))
width = 0.3
for i in range(0, 1):
    ax.bar(np.arange(12)-width, df.iloc[i], bottom=df.iloc[:i].sum(), width=width)
for j in range(1, 2):
    ax.bar(np.arange(12), df.iloc[j], bottom=df.iloc[1:j].sum(), width=width)
for k in range(2, 3):
    ax.bar(np.arange(12)+width, df.iloc[k], width=width)

plt.xticks(np.arange(12), np.arange(1, 13), fontsize=14)
plt.show()

では、順番にみていきます。

必要なライブラリのインポート

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

グラフを可視化するためのMatplotlib、演算を行うためのNumpy、データフレームを操作するためのPandasをインポートします。
この3つのライブラリはだいたいセットでインポートすることが多いですね。

 

データフレームの定義

df = pd.read_excel('Example.xlsx', sheet_name='DataFrame')
df.set_index('Date', inplace=True)
df['Saving'] = df['Income'] - df['Cost']
df = df.T

まず、エクセルにある集計用テーブルを読み込み、次にエクセルのA列にあたる月日の列をインデックス化します。
月日をインデックス化しておくと、年ごとや月ごと、必要なら四半期ごとの集計が楽にできるようになります。

また、グラフ化するために必要なので貯蓄の列も作ります。
私はエクセルには最小限のデータしか入れたくないので、Pythonで作っていっますが、エクセル上で準備しておいてもOKです。

出来上がりはこんなデータフレームです。

次がポイントで、これをfor文の繰り返し処理でグラフ化していきますが、for文は行ごとに処理をしていくのに対して、このデータフレームは各費目が列ごとにならんでいて、for文の処理と行と列が逆になっています。

そのため、数学をやった方なら線形代数でおなじみの転置行列を使い、最後の行でfor文が処理できるように行列を入れ替えています。

で、出来上がったのがこちらです。

おそらくこの形で時系列データを集計することは一般的ではないと思いますが、Pythonだとそれが一瞬で作れます。

グラフ化

fig, ax = plt.subplots(figsize=(15, 6))
width = 0.3
for i in range(0, 1):
    ax.bar(np.arange(12)-width, df.iloc[i], bottom=df.iloc[:i].sum(), width=width)
for j in range(1, 2):
    ax.bar(np.arange(12), df.iloc[j], bottom=df.iloc[1:j].sum(), width=width)
for k in range(2, 3):
    ax.bar(np.arange(12)+width, df.iloc[k], width=width)

plt.xticks(np.arange(12), np.arange(1, 13), fontsize=14)
plt.grid(axis='y', color='gainsboro')
plt.title('Monthly Balance', fontsize=16)
plt.legend(df.index[0:3], bbox_to_anchor=(1, 1), fontsize=14)

plt.show()

最初のfor文でIncome, 次でCost, 最後のでSavingを描いています。

その後x軸を1から12で設定し、見やすくするためにグリッド線を入れ、タイトルを設定し、凡例を載せています。
できあがりのグラフがこちらです。

このコードではPythonのデフォルト色を使っていますが、自分で好みの色を指定することも可能です。

最後に Pythonのメリット

お疲れ様でした。
この記事の最後として、エクセルからPythonでの管理に移行しての感想を書いてみます。

私がPythonに移行して約半年ですが、一言で言って快適です。
一番のメリットは元データをシンプルな形で持つことができる点です。

エクセルでは元データから行や列を追加して関数を書くので、その過程でデータが増え、グラフを作るのにいくつも似たようなテーブルが生まれて、「これまとめたいなー」なんていうのはよくある話ですが、Pythonはデータフレーム上で貯蓄列を作れたように、元データはそのままで加工したデータテーブルは変数として持つことができます。

そのため、元データのエクセルはシンプルで、実際私はsumifs関数くらいしか使っていません。
配列関数やindex関数、find関数など様々な関数を実装したはいいものの、自分で書いた関数式を読み解くのに時間がかかる、なんてこともないです。

もう、エクセルでの管理には戻れません。

それでは、また。


人気ブログランキング
最後まで読んで下さりありがとうございます。
面白かったらフォローしてもらえると励みになります。



Posted by Econ