霞と側杖を食らう

ほしいものです。なにかいただけるとしあわせです。[https://www.amazon.jp/hz/wishlist/ls/2EIEFTV4IKSIJ?ref_=wl_share]

日本酒アプリのさけのわデータの学習記録

 

【はじめに】

この記事は, さけのわデータ ( 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 )

stat-you1025.blogspot.com

データを取得してみたので, 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 軽快

同じ銘柄といっても, その銘柄の中での種類によって味わいが違うとはいえ, 二兎が目指している相反する性質の共存がよく表されているように思う.

 

今回のデータの構造を整理すると, こんな感じの構造になる. 

 

【学習予定】

以上で, さけのわデータの構造や扱い方が理解できたので, 次回の記事で, 日本酒の酸味に関する分類に挑戦してみる(やり方はまだ考え中で, 上手く行くかは不明).