cucumber flesh

Rを中心としたデータ分析・統計解析らへんの話題をしていくだけ

気象庁提供の潮位表、過去の気象データをRで読み込む

最近、気象庁が提供する各種データをR上で取り扱うパッケージ、jmastatsに新しい関数を追加しました。 このパッケージはちまちまと更新しており、現在のところCRANへの登録は目指していません。 ですが便利なパッケージなのでこの場で宣伝しておきます。

https://gitlab.com/uribo/jmastats

gitlab.com

今回追加したのは以下の関数です。いずれも気象庁のウェブサイトでダウンロード可能なファイルを読み込むために使います。

  • read_tide_level(), pivot_tide_level(): 潮汐観測資料から潮位表データの読み込み
  • read_jma_weather(): 過去の地点気象データを読み込む

この機能を試したい場合、パッケージをGitLab経由(GitHubではありませんので注意)でインストールする必要があります。次のコマンドを実行するとインストールが行われます。

install.packages("remotes")
remotes::install_gitlab("uribo/jmastats")
library(jmastats)

次にこれらの関数の使い方を紹介します。

潮汐観測資料

潮汐観測資料および各種潮位データ・品質管理情報のページよりダウンロード可能な、 毎時潮位満潮・干潮の時刻と潮位が記録されたテキストファイルを与えて実行します。

ダウンロード済みのローカルファイルのパスを指定しても良いですし、気象庁のURLを直接与えても良いです。また引数による年月、地点の指定も可能です。次の例は、2020年2月の「東京」のデータを対象に実行するものです。

# ファイルが置かれているパスがわかる場合は直接パスを指定すると良いです。
#d <- 
#  read_tide_level("https://www.data.jma.go.jp/gmd/kaiyou/data/db/tide/suisan/txt/2020/TK.txt")
# path引数以外の引数でデータを指定する場合(こちらは一ヶ月単位のデータになります。)
d <- 
  read_tide_level(.year = 2020, .month = 2, .stn = "TK")

d
#> # A tibble: 29 x 42
#> hry_00   hry_01   hry_02   hry_03   hry_04   hry_05   hry_06   hry_07   hry_08   hry_09   hry_10
#> [cm]     [cm]     [cm]     [cm]     [cm]     [cm]     [cm]     [cm]     [cm]     [cm]     [cm]
#> 1      176      156      143      143      153      172      194      214      229      237      236
#> 2      195      180      166      160      162      172      188      204      219      230      232
#> 3      197      190      181      174      173      179      191      204      216      224      228
#> 4      204      206      204      201      197      194      194      196      203      211      218
#> 5      197      212      220      223      221      217      212      210      210      215      223
#> 6      172      196      213      222      225      221      211      199      188      182      183
#> 7      130      164      197      222      235      234      224      208      192      180      176
#> 8      112      148      187      224      251      262      258      241      217      196      182
#> 9       87      120      162      204      240      261      264      250      223      194      172
#> 10       69       93      134      183      229      263      279      276      256      226      195
#> # … with 19 more rows, and 31 more variables: hry_11 [cm], hry_12 [cm], hry_13 [cm], hry_14 [cm],
#> #   hry_15 [cm], hry_16 [cm], hry_17 [cm], hry_18 [cm], hry_19 [cm], hry_20 [cm], hry_21 [cm],
#> #   hry_22 [cm], hry_23 [cm], date <date>, stn <chr>, low_tide_hm_obs1 <time>, low_tide_level_obs1 [cm],
#> #   high_tide_hm_obs1 <time>, high_tide_level_obs1 [cm], low_tide_hm_obs2 <time>,
#> #   low_tide_level_obs2 [cm], high_tide_hm_obs2 <time>, high_tide_level_obs2 [cm],
#> #   low_tide_hm_obs3 <time>, low_tide_level_obs3 [cm], high_tide_hm_obs3 <time>,
#> #   high_tide_level_obs3 [cm], low_tide_hm_obs4 <time>, low_tide_level_obs4 [cm],
#> #   high_tide_hm_obs4 <time>, high_tide_level_obs4 [cm]

潮位の単位がcmで記録されているので、unitsパッケージを使って単位を与えているのが特徴です。 また、元データは毎時潮位と満潮・干潮の潮位データが一つのファイルになっているので列が多いです(行数は日数に対応)。そのため、jmastatsではこのデータを分離し、縦長のデータフレームに変換する関数 pivot_tide_level()を用意しました。

read_tide_level()で読み込んだデータを引数に与えて実行します。この関数の返り値は2つのデータフレームを含んだリストです。hourlyが毎時潮位、tideが満潮・干潮の潮位となります。

d_long <- 
  d %>% 
  pivot_tide_level()
d_long
#> $hourly
#> # A tibble: 696 x 3
#> datetime            stn   tide_value
#> <dttm>              <chr>       [cm]
#> 1 2020-02-01 00:00:00 TK           176
#> 2 2020-02-01 01:00:00 TK           156
#> 3 2020-02-01 02:00:00 TK           143
#> 4 2020-02-01 03:00:00 TK           143
#> 5 2020-02-01 04:00:00 TK           153
#> 6 2020-02-01 05:00:00 TK           172
#> 7 2020-02-01 06:00:00 TK           194
#> 8 2020-02-01 07:00:00 TK           214
#> 9 2020-02-01 08:00:00 TK           229
#> 10 2020-02-01 09:00:00 TK           237
#> # … with 686 more rows
#> 
#> $tide
#> # A tibble: 112 x 6
#> date       stn   tide_level count time   tide_value
#> <date>     <chr> <chr>      <chr> <time>       [cm]
#> 1 2020-02-01 TK    low        1     09:23         238
#> 2 2020-02-01 TK    high       1     02:33         141
#> 3 2020-02-01 TK    low        2     21:35         210
#> 4 2020-02-01 TK    high       2     15:23         155
#> 5 2020-02-02 TK    low        1     09:45         232
#> 6 2020-02-02 TK    high       1     03:16         160
#> 7 2020-02-02 TK    low        2     23:18         198
#> 8 2020-02-02 TK    high       2     16:23         151
#> 9 2020-02-03 TK    low        1     10:25         228
#> 10 2020-02-03 TK    high       1     03:41         173
#> # … with 102 more rows

せっかくなので可視化してみましょう。

library(ggplot2)
library(ggforce)
d_long %>% 
  purrr::pluck("hourly") %>% 
  ggplot(aes(datetime, tide_value)) + 
  geom_line(color = "red") +
  scale_x_datetime(date_labels = "%m/%d") +
  theme_light(base_family = "IPAexGothic") +
  labs(title = "毎時潮位グラフ 2020年2月",
       subtitle = "東京")

f:id:u_ribo:20200420231912p:plain

地点名がわからないときは tide_stationデータセットで見つけることができます。なお、年によって観測地点が変わるのでそこは注意です。

tide_station
#> Simple feature collection with 1670 features and 6 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 122.95 ymin: 24.28333 xmax: 153.9833 ymax: 45.4
#> CRS:            EPSG:4326
#> # A tibble: 1,670 x 7
#> year  id    stn   station_name address                  type                  geometry
#> <chr> <chr> <chr> <chr>        <chr>                    <chr>              <POINT [°]>
#>   1 1997  1     WN    稚内         北海道 稚内市 新港町     フロート式     (141.6833 45.4)
#> 2 1997  2     AS    網走         北海道 網走市 港町       フロート式 (144.2833 44.01667)
#> 3 1997  3     HN    花咲         北海道 根室市 花咲港     フロート式 (145.5667 43.28333)
#> 4 1997  4     KR    釧路         北海道 釧路市 港町       フロート式 (144.3833 42.96667)
#> 5 1997  5     HK    函館         北海道 函館市 海岸町     フロート式 (140.7333 41.78333)
#> 6 1997  6     B3    小樽         北海道 小樽市 色内3丁目 音波式              (141 43.2)
#> 7 1997  7     SH    下北         青森県 むつ市 大字関根   音波式       (141.25 41.36666)
#> 8 1997  8     HC    八戸         青森県 八戸市 新湊3丁目 フロート式 (141.5333 40.53333)
#> 9 1997  9     MY    宮古         岩手県 宮古市 日立浜町   フロート式 (141.9833 39.63334)
#> 10 1997  10    OF    大船渡       岩手県 大船渡市 赤崎町   フロート式   (141.75 39.01667)
#> # … with 1,660 more rows

過去の地点気象データ

jmastatsには、すでにウェブスクレイピングにより気象データを取得する関数 jma_collect() がありました。一方でこの関数では地点数が多い・期間が長い場合に 気象庁のページへの負荷が多くなってしまう問題がありました。

今回追加した read_jma_weather() ではデータの用意こそユーザが各自で行う必要がありますが、任意の地点・期間のデータをRで読み込むには便利な関数となっています。 気象庁からダウンロードしたファイルのフォーマットは https://www.data.jma.go.jp/gmd/risk/obsdl/top/help3.html にあるようにやや煩雑となっていて、すぐに使える形式ではありません。 read_jma_weather()はRでの分析、可視化が素早くできるよう、自動的にデータを整形した形式で読み込みます。

関数を実行する前に対象のデータをダウンロードしておきましょう。 過去の気象データ・ダウンロードのページから関心の地点データを取得します。ここでは「つくば(舘野)」の「日平均気温」と「降水量の日合計」について、最近一ヶ月分のデータを用意しました。

d <- 
  read_jma_weather("~/Downloads/data.csv")
#> Selected station: つくば(館野)

#> Parsed with column specification:
#> cols(
#>   date = col_character(),
#>   `つくば(館野)_平均気温(℃)` = col_double(),
#>   `つくば(館野)_平均気温(℃)_品質情報` = col_double(),
#>   `つくば(館野)_平均気温(℃)_均質番号` = col_double(),
#>   `つくば(館野)_降水量の合計(mm)` = col_double(),
#>   `つくば(館野)_降水量の合計(mm)_現象なし情報` = col_double(),
#>   `つくば(館野)_降水量の合計(mm)_品質情報` = col_double(),
#>   `つくば(館野)_降水量の合計(mm)_均質番号` = col_double()
#> )

dplyr::glimpse(d)
#> Rows: 31
#> Columns: 8
#> $ date                                            <date> 2020-03-20, 2020-03…
#> $ `つくば(館野)_平均気温(℃)`                   <dbl> 12.9, 11.2, 14.7, 8.5, 6.0, 7.0,…
#> $ `つくば(館野)_平均気温(℃)_品質情報`          <dbl> 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, …
#> $ `つくば(館野)_平均気温(℃)_均質番号`          <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
#> $ `つくば(館野)_降水量の合計(mm)`               <dbl> 0.0, 0.0, 0.0, 0.0, 1.5, 0.0, 0.0…
#> $ `つくば(館野)_降水量の合計(mm)_現象なし情報`  <dbl> 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, …
#> $ `つくば(館野)_降水量の合計(mm)_品質情報`      <dbl> 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8…
#> $ `つくば(館野)_降水量の合計(mm)_均質番号`      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…

お試しいただき、改善や機能追加のリクエストをいただけると助かります。 また、こうしたRパッケージの開発を支援してくださる方も引き続き募集しています。

https://uribo.hatenablog.com/entry/2020/03/27/170257 uribo.hatenablog.com

どうぞよろしくお願いします。

jpmeshバージョン1.2.0をリリース

統計調査などで使われる標準地域メッシュをRで扱うjpmeshパッケージのバージョン1.2.0 をCRANにリリースしました。以前のバージョンは1.1.3でした。マイナーアップデートですがいくつかの変更点・新機能がありますので紹介します。

f:id:u_ribo:20200328093427p:plain

インストール

2020年3月28日現在、WindowsおよびmacOSでのバイナリ版が用意されていない状況です。これらのOSを利用されている方はインストールをもうしばらくお待ちください。

install.packages("jpmesh") # v1.2.0
library(jpmesh)
library(sf)

メッシュサイズの指定を文字列から数値で行うように

これまでのjpmeshの関数では、メッシュサイズを指定する際に 80km のような文字列での指定が必要でした。

meshcode_set(mesh_size = "80km")

coords_to_mesh(141.3468, 43.06462, mesh_size = "500m")

rmesh(1, mesh_size = "1km")

これに対して、今回リリースされたv1.2.0では1kmを1として、すべてのメッシュサイズの指定を数値で行うように変更しました。すなわち、80kmのときは80、500mでは0.5、250mメッシュサイズの場合は0.25です。

上記のコードをv1.2.0で実行する際は以下のようにします。

meshcode_set(mesh_size = 80)

coords_to_mesh(141.3468, 43.06462, mesh_size = 0.5)

rmesh(1, mesh_size = 1)

メッシュサイズの変更 - mesh_convert()

次は追加した関数です。入力に与えたメッシュコードを適当なメッシュサイズに変更する mesh_convert() を用意しました。メッシュサイズのスケールアップ・スケールダウンが簡単に行えます。

set.seed(1)
rmesh(1) %>% 
  mesh_convert(to_mesh_size = 0.25)
##  [1] "4040745711" "4040745712" "4040745713" "4040745714" "4040745721"
##  [6] "4040745722" "4040745723" "4040745724" "4040745731" "4040745732"
## [11] "4040745733" "4040745734" "4040745741" "4040745742" "4040745743"
## [16] "4040745744"

スケールダウンの機能を持つ関数として fine_separate() がありますが、こちらは変換したいメッシュサイズにするまでに繰り返しの処理が必要になる場合がありました。

rmesh(1) %>% 
  fine_separate() %>% 
  purrr::map(fine_separate) %>% 
  purrr::reduce(c) %>% 
  unique()

mesh_convert()では 80km (80)から125m (0.125)までのメッシュサイズに対応しており、柔軟にメッシュサイズの変更ができます。

set.seed(2)
rmesh(1, mesh_size = 1) %>% 
  mesh_convert(to_mesh_size = 80)
## [1] "4931"

メッシュコードを変数に含むデータフレームのsf化 - meshcode_sf()

メッシュコードを含むデータフレームを処理することがあります。

set.seed(3)
df_mesh <- 
  tibble::tibble(
    meshcode = rmesh(1, mesh_size = 1) %>% 
      fine_separate(),
    value = rnorm(4))
df_mesh
## # A tibble: 4 x 2
##   meshcode   value
##   <chr>      <dbl>
## 1 492816651 -0.293
## 2 492816652  0.259
## 3 492816653 -1.15 
## 4 492816654  0.196

ここからメッシュコードのgeometry (polygon) を生成し、sfオブジェクトとして扱うための関数が meshcode_sf() です。引数 mesh_var にメッシュコードが記録されている変数名を与えて実行します。このとき、dplyrやtidyrで変数を指定するように引用符は必要ありません。

sf_mesh <- 
  df_mesh %>% 
  meshcode_sf(mesh_var = meshcode)
class(sf_mesh)
## [1] "sf"         "tbl_df"     "tbl"        "data.frame"
sf_mesh %>% 
  st_geometry() %>% 
  plot()

f:id:u_ribo:20200328092349p:plain

この機能は自分自身がよく使っていたものなので、実装できて満足しています。

次のリリースでは?

jpmeshは現在80kmメッシュから1kmメッシュまでの基準地域メッシュ、500m、250m、125mの分割地域メッシュに対応しています。国内で使われるメッシュコードには他に100mと50mの統合地域メッシュが存在します。これらについてサポートするかが議論されています。

github.com

100mメッシュが250mメッシュと同じ桁数になってしまうのでどうにかしないといけません。

また、対象のメッシュコードが人口集中地区(DID)をはじめとした国土政策関係の区域に含まれるかを判定する関数を実装予定でいます。

github.com

ご意見あるかたはGitHub もしくは Twitter (@u_ribo)まで。

スポンサーの検討もお願いいたします。

uribo.hatenablog.com

GitHub Sponsorsの募集を始めました、よろしくお願いします。

表題の通り、GitHub Sponsorsの審査を通過しましたので告知です。

要約

私のオープンソースソフトウェア(OSS)活動を支援するための寄付の受付を開始したので何卒一考ください。

f:id:u_ribo:20200327165250p:plain

きっかけ

GitHub Sponsorsは個人およびコミュニティのOSS活動を支援するための枠組みです。R界隈では世界の @Atsushi776 が始めたのが話題となりました(彼の告知記事。私もスポンサーになりました)。

私が得意とする言語はRです。学生時代から使っていて、まあ「ちょっとわかる」程度には使えると思っています。

Rはオープンソースで使うのにお金がかかりません。エディタとしても優秀な統合開発環境のRStudioアプリケーションも無料です。また、これまでに多くの書籍、プレゼンテーション、その他資料がインターネットで公開されてきました。

過去の人々の力に支えられている。その人たちは無償で行ってくれた。それなのに「お金儲け」をするのはどうなの?」という考えが少なからずあります。一方で仕事では前職から「ほぼR 100%」です。なので「お金稼ぎ」はしています。また書籍の執筆も少なからず行っており、それによる収入もあることも事実です。

ただ今年になって、そうした見方が変わってきました。Rは多くの研究、企業・業務でも使われる、素晴らしい言語です。そこには過去・現在・未来に豊富な人材があり、自分以上に生活の基盤としている人もいるでしょう(RStudio社はまさにそれ)。そして「技術はタダじゃない」そう思い至るようになりました。

自分の価値を低く見積もってはいけない。それはコミュニティ内の他のユーザや文化にも影響します。

なぜ支援を求めるのか

GitHub Sponsorsを始める前から、OSS活動を行う・幅を広げていく上でいくつかの課題がありました。それは次のようなものです。これらはいずれもお金で解決できる面があります。

  1. 英語力の向上
  2. 国際カンファレンス参加資金
  3. OSS参加のためのマシン、サーバ、サービス経費等 ... 現在の開発環境はiMac (2017) と MacBookPro (2013) がメインです。
  4. コミュニティ運営のモチベーション、活動経費
  5. R以外の言語、特にPython, Go, Juliaの学習

いくつかの項目について説明します。

OSS活動は、大別すると自分が開発者となり進めるもの、他の人・グループが中心にいる中で参画していくものがありますが、私はどちらかというと前者が中心で、グローバルなOSS活動についてはtypoの修正や簡単な機能実装等しか行えていないことが多く、まだまだ未熟さを感じています。そこには技術的な問題の他、「英語」の障壁が存在します(言語を問わず、コミュニケーション全般の課題でもありますが)。

言わずもがな、OSSでの中心言語は英語が主流です。1. 英語力の向上OSS活動を行う上で欠かせない能力だと捉えています。また次の2. 国際カンファレンス参加で他の開発者と交流する際も必要となります。

Rコミュニティには2つの大きな国際カンファレンスが毎年行われています。Rユーザの集会的なuseR!は、毎回開催箇所(国)が変わる面白さがあります。もう一つのRStudio conference (rstudio::conf) はRStudio社主催で本社のあるアメリカ開催です。

カンファレンスへの参加は先端の情報や意見交換ができるだけでなく、GitHubTwitterでお世話になっている人たちに会える絶好の機会です!一方でいずれも海外の開催&一週間ほどの滞在で個人で気軽に行くのには現実的な問題があります。(所属する企業でサポートがあると良いのですが、私の所属組織ではそうは行きません)

最後に4. コミュニティ運営のモチベーション、活動経費です。コミュニティを維持するためには時間もお金もかかります。私はTokyo.RおよびTsukuba.Rの2つのコミュニティに関わっています。と言っても、どちらもほとんど貢献できていません。

Tokyo.Rの方は運営メンバーではありませんが、Slackコミュニティのr-wakalangの保守とRユーザと話すpodcastR Radio for the Rest of us (R3)を継続しています。

また茨城県つくば市周辺のRユーザを対象にしたTsukuba.Rも再起動したものの、定期的に行える体制が整っていません。これは会場の確保をはじめとした各種の手続きに手間取ることが原因の一つです。コミュニティの形成は一朝一夕には行きませんが、ユーザを育てるためには欠かせないものだと信じています。私の怠惰で行えていないことは大いに反省すべきでしょう。一方でこれらの活動は完全に自らの時間と金を使って行われています。私のOSS活動の最終地点は、未来のためのユーザの育成(あるいは財産の共有)だと考えています。培った技術、情報は次世代に残していきたいです。

こんなことをしています

  • Rパッケージ開発
    • CRANに登録されているもの(jpmesh ⭐️26, zipangu ⭐️21, jpndistrict ⭐️11 fgdr ⭐️5)
    • 時々 rstudio関係、rOpenSci、r-spatialのパッケージへissueやPRを出します
  • 資料公開 (執筆、スライド、ブログ)
    • このブログQiitaの記事で使ったコードはリポジトリでも公開しています。またTokyo.Rをはじめとしたイベントでの講演資料もSpeakerdeckと共にアップロードしています。
    • 更新をサボりがちですが、空間解析や機械学習のための執筆をしています。

uribo.github.io

github.com

  • 可視化プロジェクト ... あれこれとやっています。地図を使ったものが多いです。可能な限りコードを公開しています。

f:id:u_ribo:20200327165449p:plain

  • 情報発信 ... 毎日GitHubに張り付いているので、新しいパッケージや機能追加は比較的早い段階でキャッチアップしています。スポンサーに情報共有するというのはアリかもしれません。

speakerdeck.com

speakerdeck.com

サポートする意思のある人へ

ここまであれこれと宣伝でした。ではいよいよスポンサー枠のご案内です。現在5つの枠を用意していますが、

  • $3/month または $6/monthは個人枠
  • $20/month, $50, $1000 ($100ではない)を企業枠と捉えています(もちろん個人でやってくれても大歓迎)

の2つが大きくあります。月単位でのサポートも可能です。その場合、サポートを停止するのをお忘れなく。

また、スポンサーになっていただけるのはどなたでも歓迎ですが、次の条件に合っているかどうか、踏みとどまって欲しい項目をあげておきます。

  • 私の開発するRパッケージ、資料を活用している人
  • 私を通じてコミュニティ活動を支えたい人
  • 私自身を応援したい人

スポンサーへの直接のお礼や特典は今のところありませんが、感謝の気持ちは述べさせてください。加えて、支援してくれる理由やお金の用途の指定があれば教えていただけますと幸いです。

それでは、瓜生真也と未来のRコミュニティのためにどうぞよろしくお願いします。

github.com