【はじめに】
この記事は, さけのわデータ ( https://sakenowa.com )のデータを加工して利用しています. ありがとうございます!!
【学習動機】
飲んだ日本酒を記録して好みの日本酒を見つけることができるサービスの, さけのわ( https://sakenowa.com/ )のデータが無料で利用できるということは何年か前に知ってはいたのだが, なかなか利用しないままでいた. この数年で日本酒を飲んだり, 日本酒に関する本を読んだりすることで, 日本酒のドメイン知識が増えたので, それを, さけのわデータで利活用してみたいと思い立った. 個人的に最近, 日本酒の酸味に関心があるので, 酸味に関して何かしら分類ができないかと思っている. 今回の記事では, その分析をする前に, さけのわデータがどのようなデータ構造になっているのかを確かめることにする. データを扱う際にはRを使用する.
【学習記録】
公式のさけのわデータの説明を確認する ( https://muro.sakenowa.com/sakenowa-data/ ) . json形式でデータが使えて, エンコーディングはUTF-8となっている.
json形式のデータの扱いは詳しくないので, データをRで揃えてくれている先人はいないものかと探していたら, 先人の記事を発見した. このブログにRでデータを取得する方法が書かれていたので参考にしました. 今回のデータ取得のコードはほとんどをこのブログのコードに頼っています(ありがとうございます!!).
( https://stat-you1025.blogspot.com/2020/09/blog-post_18.html )
データを取得してみたので, 7つのデータの構造を確認する. 説明での括弧内は手元でのデータフレーム名や変数名を書いている. (データ取得のところは簡単に関数化しようと思ったのだけれど, 名前の不一致や格納されているデータの数の不一致などがあって, 途中で断念した.)
まずは, 必要なパッケージ読み込み.
library(tidyverse)
library(httr)
library(jsonlite)
さて, 地域一覧, 銘柄一覧, 蔵元一覧, ランキング, フレーバーチャート, フレーバータグ一覧, 銘柄ごとのフレーバータグのデータを取得し, 確認していく.
1. 地域一覧
areas(df_areas)
- id(areaId)
- name(areaname)
df_areas <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/areas") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$areas %>%
tibble::as_tibble() %>%
rename(areaId=id,
areaname=name)
df_areas
## # A tibble: 48 x 2
## areaId areaname
## <int> <chr>
## 1 1 北海道
## 2 2 青森県
## 3 3 岩手県
## 4 4 宮城県
## 5 5 秋田県
## 6 6 山形県
## 7 7 福島県
## 8 8 茨城県
## 9 9 栃木県
## 10 10 群馬県
## # ... with 38 more rows
48個データがあるので気になって確認してみたら, 47都道府県とその他がareaId 0番で入っていた.
2. 銘柄一覧
brands(df_brands)
- id(df_brands)
- name(brandname)
- breweryId
df_brands <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/brands") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$brands %>%
tibble::as_tibble() %>%
rename(brandId=id,
brandname=name)
df_brands
## # A tibble: 3,142 x 3
## brandId brandname breweryId
## <int> <chr> <int>
## 1 1 新十津川 1
## 2 2 男山 2
## 3 3 大雪乃蔵 3
## 4 4 宝川 4
## 5 5 亀甲蔵 4
## 6 7 北の誉 3
## 7 8 風のささやき 6
## 8 9 えぞ乃熊 6
## 9 10 国士無双 6
## 10 11 北の錦 7
## # ... with 3,132 more rows
3. 蔵元一覧
breweries(df_breweries)
- id(breweryId)
- name(breweryname)
- areaId
df_breweries <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/breweries") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$breweries %>%
tibble::as_tibble() %>%
rename(breweryId=id,
breweryname=name)
df_breweries
## # A tibble: 1,729 x 3
## breweryId breweryname areaId
## <int> <chr> <int>
## 1 1 金滴酒造 1
## 2 2 男山 1
## 3 3 合同酒精 1
## 4 4 田中酒造 1
## 5 5 北の誉酒造 1
## 6 6 高砂酒造 1
## 7 7 小林酒造 1
## 8 10 八戸酒造 2
## 9 12 桃川 2
## 10 13 松緑酒造 2
## # ... with 1,719 more rows
1729の酒蔵が登録されていた. 酒類製造業及び酒類卸売業の概況(令和5年アンケート) ( https://www.nta.go.jp/taxes/sake/shiori-gaikyo/seizo_oroshiuri/r05/index.htm ) の酒類製造者等及び酒類卸売業者の概要の表1を確認してみると, 清酒の製造場数は1544とある. 注1を見ると複数品目を製造していると数量が最も多い品目で計上している. その他, 既になくなった蔵も考えれば, ほとんど全てカバーされているのかと思われる.
都道府県別の蔵元の数が気になったので確認.
df_breweries %>%
left_join(df_areas,by = "areaId") %>%
group_by(areaname) %>%
summarise(n=n()) %>%
arrange(-n)
## # A tibble: 48 x 2
## areaname n
## <chr> <int>
## 1 新潟県 113
## 2 兵庫県 96
## 3 長野県 91
## 4 山形県 76
## 5 福島県 69
## 6 岐阜県 54
## 7 福岡県 54
## 8 京都府 50
## 9 広島県 50
## 10 秋田県 48
## # ... with 38 more rows
4. ランキング
ランキングデータは3つあって, yearMonth(ランキングの対象年月), overall(総合ランキング), areas(地域ランキング).
yearMonth
ランキングの対象年月がYYYYMM形式で入っている.
rankings_YM <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/rankings") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$yearMonth
rankings_YM
## [1] "202309"
overall(df_rankings_overall)
- rank
- score
- brendId
df_rankings_overall <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/rankings") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$overall %>%
tibble::as_tibble()
このままだと分からないので, 紐づけてランキングを確認.
df_rankings_overall %>%
left_join(df_brands, by="brandId")
## # A tibble: 100 x 5
## rank score brandId brandname breweryId
## <int> <dbl> <int> <chr> <int>
## 1 1 4.41 109 新政 76
## 2 2 4.10 144 十四代 96
## 3 3 4.09 792 風の森 589
## 4 4 4.09 1033 作 835
## 5 5 4.08 660 而今 488
## 6 6 4.08 258 鳳凰美田 183
## 7 7 4.07 1121 仙禽 1168
## 8 8 4.06 19 田酒 16
## 9 9 4.05 2602 赤武 898
## 10 10 4.04 975 鍋島 758
## # ... with 90 more rows
新政, 十四代, 風の森と有名な銘柄がずらりと並んでいる.
areas(df_rankings_areas)
- areaId
- ranking(中にrank, score, brandIdの情報が格納されている)
df_rankings_areas <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/rankings") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$areas %>%
tibble::as_tibble()
df_rankings_areas
## # A tibble: 48 x 2
## areaId ranking
## <int> <list>
## 1 0 <df[,3] [2 x 3]>
## 2 1 <df[,3] [25 x 3]>
## 3 2 <df[,3] [30 x 3]>
## 4 3 <df[,3] [30 x 3]>
## 5 4 <df[,3] [45 x 3]>
## 6 5 <df[,3] [50 x 3]>
## 7 6 <df[,3] [50 x 3]>
## 8 7 <df[,3] [50 x 3]>
## 9 8 <df[,3] [29 x 3]>
## 10 9 <df[,3] [29 x 3]>
## # ... with 38 more rows
ネスト化されているので, unnestで解除して, 他のデータを紐づけて, 神奈川県のランキングを確認してみる.
df_rankings_areas %>%
unnest(cols = everything()) %>%
left_join(df_areas, by="areaId") %>%
left_join(df_brands, by="brandId") %>%
filter(areaname=="神奈川県")
## # A tibble: 20 x 7
## areaId rank score brandId areaname brandname breweryId
## <int> <int> <dbl> <int> <chr> <chr> <int>
## 1 14 1 4.41 323 神奈川県 いづみ橋 231
## 2 14 2 4.09 1022 神奈川県 天青 1071
## 3 14 3 4.06 1584 神奈川県 残草蓬莱 235
## 4 14 4 4.05 324 神奈川県 相模灘 232
## 5 14 5 4.05 1671 神奈川県 松みどり 942
## 6 14 6 4.02 1527 神奈川県 隆 237
## 7 14 7 4.02 326 神奈川県 昇龍蓬莱 235
## 8 14 8 4.02 1677 神奈川県 泉橋 231
## 9 14 9 4.01 327 神奈川県 丹沢山 237
## 10 14 10 4.01 66397 神奈川県 雨降 1144
## 11 14 11 4.01 325 神奈川県 白笹鼓 233
## 12 14 12 4.01 2107 神奈川県 盛升 1065
## 13 14 13 4.01 2867 神奈川県 黒とんぼ 231
## 14 14 14 4.01 39164 神奈川県 HINEMOS 1859
## 15 14 15 4.01 2424 神奈川県 箱根山 1125
## 16 14 16 4.01 1829 神奈川県 松美酉 942
## 17 14 17 4.01 3422 神奈川県 鎌倉栞 1071
## 18 14 18 4.01 3417 神奈川県 湘南 1071
## 19 14 19 4.01 3386 神奈川県 箱根街道 1012
## 20 14 20 4.01 3013 神奈川県 四季の箱根 942
いづみ橋や天青, 残草蓬莱(ざるそうほうらい)はたしかに飲んだことがある. そういえば, スコアがどのように付けられているのかが分からないので気になった. さけのわのランキングページを見てみると, 「さけのわでの人気の度合いをお気に入り、殿堂入りと最近のチェックイン数を元にした独自のアルゴリズムにより算出したスコア順で表示しています。」とあるからスコアは非公開の算出方法は非公開と思われる.
5. フレーバーチャート
flavorCharts(df_flavor_charts)
- brandId
- f1(hanayaka) : 華やかのスコア
- f2(hojun) : 芳醇のスコア
- f3(juko) : 重厚のスコア
- f4(odayaka) : 穏やかのスコア
- f5(dry) : ドライのスコア
- f6(keikai) : 軽快のスコア
df_flavor_charts <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/flavor-charts") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$flavorCharts %>%
tibble::as_tibble() %>%
rename(hanayaka=f1,
hojun=f2,
juko=f3,
odayaka=f4,
dry=f5,
keikai=f6)
df_flavor_charts
## # A tibble: 1,322 x 7
## brandId hanayaka hojun juko odayaka dry keikai
## <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2 0.267 0.502 0.328 0.424 0.463 0.419
## 2 3 0.340 0.394 0.184 0.542 0.466 0.429
## 3 4 0.467 0.441 0.295 0.314 0.278 0.569
## 4 7 0.213 0.481 0.265 0.680 0.337 0.278
## 5 9 0.436 0.526 0.293 0.417 0.259 0.455
## 6 10 0.334 0.474 0.332 0.447 0.417 0.424
## 7 11 0.309 0.548 0.441 0.492 0.262 0.314
## 8 12 0.503 0.462 0.216 0.275 0.402 0.500
## 9 14 0.219 0.354 0.241 0.711 0.411 0.308
## 10 17 0.372 0.536 0.384 0.473 0.294 0.342
## # ... with 1,312 more rows
6. フレーバータグ一覧
tags(df_tags)
- id(tagIds)
- tag
df_tags <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/flavor-tags") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$tags %>%
tibble::as_tibble() %>%
rename(tagIds=id)
df_tags
## # A tibble: 141 x 2
## tagIds tag
## <int> <chr>
## 1 2 酸味
## 2 3 辛口
## 3 5 旨味
## 4 6 フルーティ
## 5 7 スッキリ
## 6 9 しっかり
## 7 12 甘味
## 8 16 穀物
## 9 17 苦味
## 10 19 コク
## # ... with 131 more rows
タグの種類のマスタになっていて, 次の銘柄ごとのフレーバータグで使われている.
7. 銘柄ごとのフレーバータグ
flavor
- brandId
- tagIds
df_flavortags <-
httr::GET("https://muro.sakenowa.com/sakenowa-data/api/brand-flavor-tags") %>%
httr::content(as = "text", encoding = "utf-8") %>%
jsonlite::fromJSON() %>%
.$flavorTags %>%
tibble::as_tibble()
df_flavortags
## # A tibble: 2,800 x 2
## brandId tagIds
## <int> <list>
## 1 1 <int [0]>
## 2 2 <int [20]>
## 3 3 <int [6]>
## 4 4 <int [6]>
## 5 5 <int [5]>
## 6 7 <int [0]>
## 7 8 <int [1]>
## 8 9 <int [20]>
## 9 10 <int [20]>
## 10 11 <int [20]>
## # ... with 2,790 more rows
各銘柄に何のフレーバータグが付いているかを教えてくれる.
試しに複雑な味わいが印象的な二兎というお酒のフレーバータグを確認してみよう.
df_flavortags %>%
unnest(cols = everything()) %>%
left_join(df_brands, by="brandId") %>%
left_join(df_tags, by="tagIds") %>%
filter(brandname=="二兎")
## # A tibble: 20 x 5
## brandId tagIds brandname breweryId tag
## <int> <int> <chr> <int> <chr>
## 1 4195 80 二兎 987 ガス
## 2 4195 2 二兎 987 酸味
## 3 4195 20 二兎 987 バランス
## 4 4195 5 二兎 987 旨味
## 5 4195 17 二兎 987 苦味
## 6 4195 12 二兎 987 甘味
## 7 4195 90 二兎 987 複雑
## 8 4195 6 二兎 987 フルーティ
## 9 4195 48 二兎 987 フレッシュ
## 10 4195 67 二兎 987 ジューシー
## 11 4195 9 二兎 987 しっかり
## 12 4195 24 二兎 987 綺麗
## 13 4195 42 二兎 987 メロン
## 14 4195 26 二兎 987 華やか
## 15 4195 100 二兎 987 さわやか
## 16 4195 38 二兎 987 余韻
## 17 4195 7 二兎 987 スッキリ
## 18 4195 23 二兎 987 キレ
## 19 4195 34 二兎 987 濃厚
## 20 4195 126 二兎 987 軽快
同じ銘柄といっても, その銘柄の中での種類によって味わいが違うとはいえ, 二兎が目指している相反する性質の共存がよく表されているように思う.
今回のデータの構造を整理すると, こんな感じの構造になる.
【学習予定】
以上で, さけのわデータの構造や扱い方が理解できたので, 次回の記事で, 日本酒の酸味に関する分類に挑戦してみる(やり方はまだ考え中で, 上手く行くかは不明).