家計簿を CSV ファイルで記入して、R で加工して、ggplot2 で表示
背景
家計簿をつけることは、自分の経済状況を把握する上で、とても重要な指標になる。家計簿をつけることができる人間は、自己管理や忍耐力などのさまざまな面で評価される。しかしながら、私にとって「家計簿をつける」ことは非常に困難だ。だって面倒なんだもん。
通常の家計簿では、費目(品名など)や用途(消耗品、嗜好品など)なんかで分けて、月ごとに合計出して・・・なんてやるわけです。こんなの面倒すぎて、やってられない。菓子パンは食料品か嗜好品か?なんてことで悩みたくない。つーか、そんなに詳細につけたところで、意味があるのか?後で見直して、「あー、先月は嗜好品がちょっと多かったなぁ。今月は抑えるか。」なんてことになるのか?なる人は立派です。ていうかそういう人は家計簿つけれないとかで悩まないんだろう。私は悩む。家計簿をつけたい!でも面倒。どうにか簡単に楽しくできないものか。
目的
家計簿を、出来る限り有益な情報を残しつつ、簡単につけることができる方法を模索する。
思考
家計簿の意味は、
- 収入と出費を明確にすることで、現状を把握しコントロールする
- 過去から現在までの傾向を探ることで、将来的な予測を行うことができる
といったところか。
1.に関しては、金銭の動きだけを記すことで事足りる。
2.に関しては、何に出費したのか、その目的はなんだったのか、といった情報もいくらか盛り込まないといけないだろう。つまり、家計簿で費目を分けて細かく記述する意味は、将来予測のためである。となるともちろん、統計的な知識が必要になる。逆に言えば、どんなに細かい情報を残していたとしても、それを分析する力がなければ意味が無い(それにこういうデータは分析者が欲しい情報とは異なることが多いのだ)。以上のことをふまえて、どこまで細かくつけるか、ではなく、どういった予測が行いたいのか、に注目することで、記述法が見えてきた。
私が知りたい予測は、何にいくら使いそうか、なんてことじゃない。そんなのは大体変わらないし、変わるとしても計画的に購入しているから問題ない。ここで知りたいのは、「どこで使いそうか」だ。つまり、コンビニで弁当を買うのとスーパーで買うのとでは、後者のほうが明らかに安い(前者が明らかにおいしい)。買うもの自体は変わらないのに、買う場所によって金額が違うのだ。つまり、家計簿によって、どこで出費する傾向が強いかが分かれば、その場所に行くことを制限する抑止力として働き、結果として利益につながるはずだ。
実験
記述する項目は、時間、場所、金額の3点にする。こうすると、レシート1枚が一つのデータセットになる。記述するファイルは何でも良いけど、ここでは CSV ファイル(カンマ区切りのデータ)とする。つまり、
datetime | place | expense |
---|---|---|
2012-01-05 03:51:00 | A店 | 1240 |
2012-01-07 20:26:00 | G店 | 1413 |
2012-01-05 23:07:00 | B店 | 440 |
2012-01-05 23:21:00 | A店 | 548 |
2011-12-19 15:48:00 | E店 | 438 |
2012-01-02 22:54:00 | A店 | 557 |
2012-01-07 05:09:00 | A店 | 1341 |
2012-01-07 20:29:00 | B店 | 480 |
... | ... | ... |
みたいな感じ。データは決して自分で整理せず、あくまでレシート内容を1行に書くに留める。整理は EXCEL なんかだと煩雑になるので、R で行うことにする(趣味の問題か)。
まずはデータの読み込み。
options(encoding="SJIS") cost <- read.csv("HouseholdAccountBook.csv",header=T)
これで、cost にデータフレームとして読み込まれる。
次に、時間を計算するために数値として変換する。
cost$datetime <- as.POSIXct(cost$datetime,'%Y-%m-%d %H:%M:%S') # 時間文字列を数値として扱うために変換 cost <- cost[order(cost$datetime),] # 時間順に昇順ソート cost <- cbind(cost, data.frame(month=format(cost$datetime,"%Y年%m月"),day=format(cost$datetime,"%d"))) # データに月と日のカテゴリ変数を追加
さらに、月別の累積金額を追記しておく。
cum <- by(cost$expense,cost$month,cumsum) # 月ごとの累積金額 cum.d <- data.frame() for(c in cum){ # 累積金額をデータフレームに cum.d <- rbind(cum.d, data.frame(cum.expense=c)) } cost <- cbind(cost,cum.d) # 元データに結合
また、月別の合計金額をグラフ中にテキストで表示するために準備。
cost.cum <- as.data.frame(xtabs(expense~month, cost)) # 月別合計金額 colnames(cost.cum) <- c("month","cum.expense") # 列名を元データに合わせる cost.cum <- merge(cost,cost.cum) # 元データとマージ(日時を付加するため)
準備完了。いよいよ ggplot2 でグラフ化する。
g <- ggplot(cost) # 元データ g <- g + geom_bar(aes(x=datetime,weight=expense,group=place,fill=place),colour="grey90",binwidth=1*24*60*60) # 横軸に日時、縦軸に金額、場所ごとに色分け、幅は1日ごとに g <- g + geom_point(aes(x=datetime,y=cum.expense),colour=cCyan,shape=1,size=3) # 累積金額をポイントで g <- g + geom_line(aes(x=datetime,y=cum.expense),colour=cCyan) # ラインで g <- g + geom_text(data=cost.cum,aes(x=datetime,y=cum.expense,label=cum.expense),hjust=1.2,vjust=0.5) # 月別合計金額を最後の点の横に記述 g <- g + geom_smooth(aes(x=datetime,y=cum.expense)) # 近似曲線 g <- g + scale_x_datetime(major="1 week", format="%b%d") # 横軸を週刻みに g <- g + facet_grid(.~month,scales="free") # 月別にグラフを分ける g <- g + opts(title=sprintf("家計簿")) # グラフタイトル g <- g + labs(x="日付",y="出費") # 軸名 g grid.gedit("text", gp=gpar(fontfamily="HiraMaruProN-W4")) # 日本語に対応するため(Mac以外の場合はfontfamilyをいじる必要がある)
出来た図がこれ。
なかなかいい感じ。累積金額が直線的に伸びているのが分かるし、どこで購入しているかも分かりやすい。
次に、場所ごとの合計金額を月別に表示してみよう。まずはデータを加工する。
each.cost <- as.data.frame(xtabs(expense~place+month,cost)) # 場所別の月別合計(その月にどこでいくら使ったか) each.cum <- by(each.cost$Freq,each.cost$month,cumsum) # 場所別にしたときの累積(後でテキストで記述するため) each.cum.d <- data.frame() for(c in each.cum){ # 累積金額をデータフレームに each.cum.d <- rbind(each.cum.d, data.frame(cum.expense=c)) } each.cost <- cbind(each.cost,each.cum.d) # 場所別の月別合計に結合
さて、図示。
g <- ggplot(each.cost) g <- g + geom_bar(aes(x=month,weight=Freq,fill=place,colour=place),colour="grey90") # 場所別で積み重ねる g <- g + geom_text(aes(x=month,y=cum.expense-Freq/2,label=paste(place,"=",Freq,sep=""),group=month),position=position_jitter(),size=4) # 場所別の合計金額をグラフ内に記述 g <- g + opts(title=sprintf("家計簿(場所別)")) # タイトル g <- g + labs(x="月",y="出費(累積)") # 軸名 g grid.gedit("text", gp=gpar(fontfamily="HiraMaruProN-W4")) # 日本語用
A店での出費が多いなぁ。なんてことが分かりやすい。今後は CSV データを記入していくだけで、R が図にしてくれる。もっと詳細な分析がしたかったら、そのまま R の関数に当てはめることが可能だ。