💻
日本版 Google COVID-19 Forecast データを取得する Go パッケージを作ってみた
週末の余暇を利用して日本版 Google COVID-19 Forecast データを取得するコマンドライン・ツールを作ってみたのだが
これ自体は Go で書いているのでパッケージとしても利用できる。リポジトリの sample ディレクトリにいくつかコード例を置いているので参考にして欲しい。
たとえば
// +build run
package main
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"os"
"github.com/spiegel-im-spiegel/cov19jpn/entity"
"github.com/spiegel-im-spiegel/cov19jpn/fetch"
"github.com/spiegel-im-spiegel/cov19jpn/filter"
"github.com/spiegel-im-spiegel/cov19jpn/values/prefcodejpn"
)
func main() {
r, err := fetch.Web(context.Background(), &http.Client{})
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer r.Close()
es, err := fetch.Import(
r,
filter.New(
prefcodejpn.TOTTORI,
prefcodejpn.SHIMANE,
prefcodejpn.OKAYAMA,
prefcodejpn.HIROSHIMA,
prefcodejpn.YAMAGUCHI,
),
)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
list := entity.NewList(es)
list.Sort()
_, _ = io.Copy(os.Stdout, bytes.NewReader(list.EncodeCSV()))
}
などとすれば中国5県のデータを抽出できる。
既にローカルにダウンロードした CSV ファイルを使うのであれば
r, err := fetch.Web(context.Background(), &http.Client{})
の代わりに
r, err := fetch.File("./forecast_JAPAN_PREFECTURE_28.csv")
としてもOK。
fetch.Import() 関数の結果は
package entity
import (
"encoding/json"
"github.com/spiegel-im-spiegel/cov19jpn/values/date"
"github.com/spiegel-im-spiegel/cov19jpn/values/prefcodejpn"
)
type Entity struct {
JapanPrefectureCode prefcodejpn.Code `json:"japan_prefecture_code"`
PrefectureName string `json:"prefecture_name"`
TargetPredictionDate date.Date `json:"target_prediction_date"`
CumulativeConfirmed *json.Number `json:"cumulative_confirmed,omitempty"`
CumulativeConfirmedQ0025 *json.Number `json:"cumulative_confirmed_q0025,omitempty"`
CumulativeConfirmedQ0975 *json.Number `json:"cumulative_confirmed_q0975,omitempty"`
CumulativeDeaths *json.Number `json:"cumulative_deaths,omitempty"`
CumulativeDeathsQ0025 *json.Number `json:"cumulative_deaths_q0025,omitempty"`
CumulativeDeathsQ0975 *json.Number `json:"cumulative_deaths_q0975,omitempty"`
HospitalizedPatients *json.Number `json:"hospitalized_patients,omitempty"`
HospitalizedPatientsQ0025 *json.Number `json:"hospitalized_patients_q0025,omitempty"`
HospitalizedPatientsQ0975 *json.Number `json:"hospitalized_patients_q0975,omitempty"`
Recovered *json.Number `json:"recovered,omitempty"`
RecoveredQ0025 *json.Number `json:"recovered_q0025,omitempty"`
RecoveredQ0975 *json.Number `json:"recovered_q0975,omitempty"`
CumulativeConfirmedGroundTruth *json.Number `json:"cumulative_confirmed_ground_truth,omitempty"`
CumulativeDeathsGroundTruth *json.Number `json:"cumulative_deaths_ground_truth,omitempty"`
HospitalizedPatientsGroundTruth *json.Number `json:"hospitalized_patients_ground_truth,omitempty"`
RecoveredGroundTruth *json.Number `json:"recovered_ground_truth,omitempty"`
ForecastDate date.Date `json:"forecast_date"`
NewDeaths *json.Number `json:"new_deaths,omitempty"`
NewConfirmed *json.Number `json:"new_confirmed,omitempty"`
NewDeathsGroundTruth *json.Number `json:"new_deaths_ground_truth,omitempty"`
NewConfirmedGroundTruth *json.Number `json:"new_confirmed_ground_truth,omitempty"`
PrefectureNameKanji string `json:"prefecture_name_kanji,omitempty"`
}
で定義される構造体の配列として返されるので,そのまま JSON 形式に encode することも可能である。また entity.NewList() 関数で entity.EntityList 型にラッピングすればソートやデータの絞り込みや CSV への encode 等が楽にできるようになる。
棒グラフについては
// +build run
package main
import (
"context"
"fmt"
"net/http"
"os"
"github.com/spiegel-im-spiegel/cov19jpn/chart"
"github.com/spiegel-im-spiegel/cov19jpn/entity"
"github.com/spiegel-im-spiegel/cov19jpn/fetch"
"github.com/spiegel-im-spiegel/cov19jpn/filter"
"github.com/spiegel-im-spiegel/cov19jpn/values/prefcodejpn"
)
func main() {
r, err := fetch.Web(context.Background(), &http.Client{})
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer r.Close()
prefcode := prefcodejpn.TOKYO
es, err := fetch.Import(
r,
filter.New(prefcode),
)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
list := entity.NewList(es)
hlist := chart.New(list.StartDayMeasure(), list.EndDayMeasure().AddDay(7), 7, list)
if err := chart.MakeHistChart(hlist, prefcode.Title(), "./output.png"); err != nil {
fmt.Fprintln(os.Stderr, err)
}
}
とすればコマンドライン版と同じ
てな感じの出力を得られる。まぁ,グラフについては好みなどもあるので,あまり参考にならないだろう。私はデザイン・センスが壊滅してるので(笑)
よろしかったらどうぞ。
参考リンク
Discussion