データベースからグラフ作成 Ruby
- 歩行テーブルと気象データを日付でジョイントしたビューから、グラフ化する
- 歩行距離、日平均気温の時系列折れ線グラフ
- 歩行距離と気温は縮尺が違うので、歩行距離に合わせる
- 期間内天候比率を円グラフ化するが、要素が多いとエラーとなるので、比率が低いデータは、「その他」として集計
- グラフライブラリーでは標準フォントが日本語に対応していないので、ttfファイルを指定
- 結果ha,pngファイルとして生成される
require "date" require 'gruff' # 棒グラフ # gruff-example.rb # g = Gruff::Bar.new # エリアグラフ # gruff-example.rb # g = Gruff::Area.new # 横棒グラフ # gruff-example.rb # g = Gruff::SideBar.new # 円グラフ # gruff-example.rb # g = Gruff::Pie.new # 日本語対応してないから # gruff-example.rb # g.font = '適当なフォント名.ttf' require 'sqlite3' # sqlite3読み込み puts "$0:#{$0}" begin db = SQLite3::Database.new 'health.db' rescue SQLite3::SQLException => e puts "open database return: " puts "#{e}\n" end table_name = "vwalking" g = Gruff::Line.new('1024x768') g.font = 'msgothic.ttf' #文字サイズの変更 g.legend_font_size = 20 g.title = "Walking and weather" # g.theme_37signals a_distance = [] a_weater = [] a_avgtemp = [] a_wdate = [] a_Weatherreport = { nil => nil } sql = "select wdate, wdate,walkingdistance,avgtemp,Weatherreport from vwalking;" begin n = 0 db.execute(sql) do |row| a_distance << row[2] a_avgtemp << row[3].to_f/5 a_wdate << row[0] n += 1 if a_Weatherreport[ row[4] ] == nil a_Weatherreport[ row[4] ] = 1 else a_Weatherreport[ row[4] ] += 1 end end rescue SQLite3::SQLException => e puts "#{sql} database return:}" puts "#{e}\n" end sql = "select count(wdate), max(wdate), min(wdate),avg(walkingdistance),avg(avgtemp) from vwalking;" cnt = 0 fromdate = "" todate = "" avgtemp = 0 avgwalk = 0 begin db.execute(sql) do |row| cnt = row[0] todate = row[1] fromdate = row[2] avgtemp = row[4] avgwalk = row[3] end rescue SQLite3::SQLException => e puts "#{sql} database return:}" puts "#{e}\n" end puts "record:#{cnt.to_s} #{sql} return\n}" db.close puts "database close return\n}" puts 'start:' + fromdate + ' to:' + todate + "\n" total_msg = "合計件数:#{cnt} 平均歩行距離(km):#{avgwalk.to_s} 期間内平均気温(℃):#{avgtemp.to_s}\n" puts total_msg # labels:ハッシュで列名を指定する。すべての列に指定しなくても良い。 wdate = { 0 => "yyyy/mm/dd" } cnt = 0 a_wdate.each_with_index do |n, i| if i.modulo(100) == 0 wdate [i] = "." else wdate [i] = nil end cnt += 1 end wdate[0] = fromdate # 先頭ラベル wdate[cnt - 1] = todate # 最終ラベル a_averaget = a_avgtemp.map { |n| (avgtemp.to_f/5).round(3) } a_averagew = a_distance.map { |n| avgwalk } g.labels = wdate g.data "歩行距離(km):", a_distance g.data "期間内平均気温(℃):", a_avgtemp g.data "合計件数:#{cnt} 平均歩行距離(km):#{((avgwalk.to_f).round(3)).to_s}", a_averagew, '#0000ff' #blue g.data "期間内平均気温(℃):#{(avgtemp.to_f).round(3).to_s}", a_averaget, '#ff0000' # red g.write('gruff-walkingWeatherline.png') g = Gruff::Pie.new('1024x768') g.font = 'msgothic.ttf' #文字サイズの変更 g.legend_font_size = 20 g.title = "Walking and weather" #0を頂点にする。デフォルトだと右90度から始まる。 g.zero_degree = -90 #値をソートしない(デフォルトはtrue) # g.sort = false # 値の微細なデータをその他として集計 cnt = 0 a_Weatherreport.each do | key, value| if value.to_i < 20 cnt += value.to_i end end a_Weatherreport["その他"] = cnt.to_i # 集計した値の微細なデータを削除 a_Weatherreport.delete_if do |key, value| value.to_i < 20 end # p a_Weatherreport a_Weatherreport.each do | key, value| if value != nil p "'#{key.to_s}', [#{value.to_i}]" g.data "'#{key.to_s}'", [value.to_i] end end g.write('gruff-walkingWeatherpie.png')
実行結果