ujimushi(@旧sradjp(15364))の日記

旧スラドの日記の引越先です

([xy]|)ticks(Plots.jl (GR))

どうでもいいことから説明していくこのPlots.jl解説シリーズ。 今回は目盛り(tick)です。今までの紹介の中では役に立つ方かもしれません。

Axisアトリビュート全般

今回のticksAxisアトリビュートです。Axisアトリビュートは2Dプロットの場合, 頭に,xyをつけると,それぞれのAxisのみの指定,xyをつけないと両方のAxisの指定になります。

3Dプロットの場合はzもからんでくるのですが,ここでは2Dなので関係ありません。

別名

tickstickしかありません。 x, y座標個別も含めると,xtikcsxtickyticksytickで全てです。

設定できる値

次の5通りです。

  1. :auto(default), true
  2. :none, false, nothing
  3. :native
  4. AbstractVector{Real}
  5. Tuple(AbstractVector{Real}, AbstractVector{AbstractString})

例を次に示します。

「1.」,「2.」の例

「1.」はチックを表示(自動),「2.」はチックを表示しない設定です。

using Plots
import GR
gr()

plot(
    plot(sin; xticks=true, yticks=false, title="xticks=true\nyticks=false",
         right_margin=(-0.5, :cm)),
    plot(sin; xticks=:none, yticks=:auto, title="xticks=:none\nyticks=:auto");
thickness_scaling=1.5, gridalpha=0.5)

savefig("ticks_true_false_none_auto.png")

グリッドも同時に表示しないようになるようですね。

「3.」はよく分からない(バックエンド側で表示)ので飛ばします。

「4.」の例

「4.」は数値のVector型を指定してチックを自分で指定します。

using Plots
import GR
gr()

plot(sin; xticks=[-4, -1, 0, 2, 5],
     yticks=[-1.0, -0.3, 0.5, 0.9], gridalpha=0.5,
     title="xticks=[-4, -1, 0, 2, 5]\nyticks=[-1.0, -0.3, 0.5, 0.9]",
     titlelocation=(0.5, 0.5))

savefig("ticks_manual.png")

「5.」の例

「5.」は(数値のVector型,文字列のVector型)のTuple型を指定します。

ついでなので,ちょっとしたhtmlからデータを読み込む例を示します。

今回は気象庁のホームページの過去の気象データから 大阪市の2024年1月1日の10分おきの気温データを読み込んでみます。

実際にホームページから大阪府大阪市2024年1月1日の10分おきのデータのURLは次の通りです。

url = (
    "https://www.data.jma.go.jp/" *
    "obd/stats/etrn/view/10min_s1.php?" *
    "prec_no=62&block_no=47772&year=2024&month=1&day=1&view="
)

,を入れないで()で挟むとタプルにならないのを利用して長い文字列を複数行に分けて設定しています。

で,上のurlを使ってホームページからhtmlをダウンロードしてみます。次のような感じ。

using HTTP

http = HTTP.get(url)
html = http.body |> String

JuliaのREPLの表示ではとっても見づらいので,ブラウザのソース表示から確認します。

<tr class="mtx">の要素のみ取得すると見通しが良さそうです。そこで,EzXMLのパッケージでパースします。

using EzXML
doc = html |> parsehtml

EzXMLxpathが使えるので,ぐぐって見つけたxpathのチートシートを参照して,REPLで試行錯誤しながら<tr class="mtx">の要素を取得してみます。

julia> nd = findall("//tr[@class=\"mtx\"]", doc)
146-element Vector{EzXML.Node}:
 EzXML.Node(<ELEMENT_NODE[tr]@0x0000000001b72d40>)
 EzXML.Node(<ELEMENT_NODE[tr]@0x0000000002479e50>)
 EzXML.Node(<ELEMENT_NODE[tr]@0x0000000002713590>)
 
 EzXML.Node(<ELEMENT_NODE[tr]@0x0000000008717fc0>)
 EzXML.Node(<ELEMENT_NODE[tr]@0x000000000871a0b0>)
 EzXML.Node(<ELEMENT_NODE[tr]@0x000000000871c1a0>)
 EzXML.Node(<ELEMENT_NODE[tr]@0x000000000871e290>)
 EzXML.Node(<ELEMENT_NODE[tr]@0x00000000088389d0>)
 EzXML.Node(<ELEMENT_NODE[tr]@0x000000000883aac0>)

取れたっぽいです。

julia> nd[1]
EzXML.Node(<ELEMENT_NODE[tr]@0x0000000001b72d40>)

julia> nd[1].content
"時分気圧(hPa)降水量(mm)気温(℃)相対湿度(%)風向・風速(m/s)日照時間(分)"

julia> elements(nd[1])
7-element Vector{EzXML.Node}:
 EzXML.Node(<ELEMENT_NODE[th]@0x000000000664c8c0>)
 EzXML.Node(<ELEMENT_NODE[th]@0x00000000026b87a0>)
 EzXML.Node(<ELEMENT_NODE[th]@0x0000000007b829a0>)
 EzXML.Node(<ELEMENT_NODE[th]@0x000000000244f470>)
 EzXML.Node(<ELEMENT_NODE[th]@0x00000000023eaaa0>)
 EzXML.Node(<ELEMENT_NODE[th]@0x00000000023243b0>)
 EzXML.Node(<ELEMENT_NODE[th]@0x0000000007fea110>)

julia> elements(nd[1])[1]
EzXML.Node(<ELEMENT_NODE[th]@0x000000000664c8c0>)

julia> elements(nd[1])[1].content
"時分"

一行目はタイトル行っぽいです。

julia> nd[2]
EzXML.Node(<ELEMENT_NODE[tr]@0x0000000002479e50>)

julia> nd[2].content
"現地海面平均風向最大瞬間風向"

二行目もタイトル行の続きっぽいです。

julia> map(ele-> ele.content, elements(nd[3]))
11-element Vector{String}:
 "00:10"
 "1004.9"
 "1015.0"
 "0.0"
 "9.9"
 "71"
 "1.7"
 "西北西"
 "4.1"
 "西"
 ""

三行目からはデータで,気温は5列目っぽいです。

以上をまとめてグラフ表示までやってみます。

using HTTP
using EzXML
using Plots
import GR
gr()

url = (
    "https://www.data.jma.go.jp/" *
    "obd/stats/etrn/view/10min_s1.php?" *
    "prec_no=62&block_no=47772&year=2024&month=1&day=1&view="
)

# HTMLバース時のWarningがうざいのでdevnullに捨てる
doc = redirect_stdio(stderr=devnull) do
    http = HTTP.get(url)
    http.body |> String |> parsehtml
end
node_all = findall("//tr[@class=\"mtx\"]", doc)
時刻文字列 = map(nd -> elements(nd)[1].content, node_all[3:end])
気温 = map(nd -> parse(Float64, elements(nd)[5].content), node_all[3:end])

plot(eachindex(気温), 気温, label="Ta",
     xticks=(eachindex(気温)[6:6:end], 時刻文字列[6:6:end]),
     guidefontfamily="ipag", xrotation=45, ylabel="気温 [℃]", xlabel="時刻",
     title="2024年1月1日の大阪市の気温", titlefontfamily="ipag")

savefig("osaka-temperature-2024-01-01.png")

欠測値があると面倒なのですが,その処理は今回省いています。なのでコンパクトなコードです。 ここでは簡便に,xの値をeachindex(気温)にして,x軸のtickのラベルで時刻を表現しています。 もちろん時刻をxに設定しても可能です。

注意点

  • 上のグラフは気象庁の過去の気象データの記録のデータを利用しています
  • 気象庁のホームページのhtmlフォーマットは予告なく変わることがあると思うので,この記事を書いた時点でうまく読み込めていた,ということで 将来的には読み込めない可能性が高いので,あくまで参考です。