総務省統計局の家計調査データからチョコレートを分析する

## はじめに

前回の記事で総務省統計局から取得したデータを加工し、扱いやすくしました

https://qiita.com/RyoWakabayashi/items/4bac70408c80426180e5

加工結果はこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/explorer/%E5%AE%B6%E8%A8%88%E6%94%AF%E5%87%BA%E7%B5%B1%E8%A8%88_%E5%93%81%E7%9B%AE%E5%B9%B4%E6%9C%88%E5%88%A5.csv

今回はこの加工したデータを使って、完全にバレンタインに遅れていますがチョコレートの分析を行います

例によって Livebook を使います

https://livebook.dev/

実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/explorer/chocolate_statistics.livemd

## 出典

以下のデータを加工して作成

総務省統計局ホームページ

家計調査（家計収支編）　時系列データ（二人以上の世帯）

<https://www.stat.go.jp/data/kakei/longtime/index.html#time>

- 月 全品目（2015年改定）
- 月 全品目（2020年改定）

（2023年2月20日に利用）

## セットアップ

必要なモジュールをインストールします

```elixir
Mix.install([
  {:explorer, "~> 0.5"},
  {:kino, "~> 0.8"},
  {:kino_vega_lite, "~> 0.1"},
  {:req, "~> 0.3"}
])
```

- [Explorer](https://github.com/elixir-nx/explorer): データ分析
- [Kino](https://github.com/livebook-dev/kino): 強力な UI/UX
- [Kino VegaLite](https://github.com/livebook-dev/kino_vega_lite): グラフ描画
- [Req](https://github.com/wojtekmach/req): HTTP通信(データダウンロード)

## 準備

Explorer を使うための準備をします

```elixir
alias Explorer.DataFrame
alias Explorer.Series
require Explorer.DataFrame
```

`alias` によって `Explorer.` を省略できるようになります

`require Explorer.DataFrame` によって、データ解析時にクエリが使えるようになります

詳細は以下の記事を参照してください

https://qiita.com/RyoWakabayashi/items/053296b36d8744aca9ca

## データ取得

加工済データをダウンロードし、データフレームに読み込みます

```elixir
household_df =
  "https://raw.githubusercontent.com/RyoWakabayashi/elixir-learning/main/livebooks/explorer/%E5%AE%B6%E8%A8%88%E6%94%AF%E5%87%BA%E7%B5%B1%E8%A8%88_%E5%93%81%E7%9B%AE%E5%B9%B4%E6%9C%88%E5%88%A5.csv"
  |> Req.get!()
  |> then(&DataFrame.load_csv!(&1.body))

Kino.DataTable.new(household_df)
```

![year_month.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/669f5bcd-4007-ede0-bf76-ea299f8fd38a.png)

データは品目分類毎、年月毎に世帯平均の支出金額を持っています

## 月次推移

`符号 == "352"` でチョコレートのデータだけを抽出します

```elixir
choco_df = DataFrame.filter(household_df, 符号 == "352")

Kino.DataTable.new(choco_df)
```

月次推移を VegaLite でグラフ化します

```elixir
month = Series.to_list(choco_df["年月"])
expenses = Series.to_list(choco_df["支出金額"])

VegaLite.new(width: 700, title: "チョコレート支出金額推移")
|> VegaLite.data_from_values(x: month, y: expenses)
|> VegaLite.mark(:line, tooltip: true)
|> VegaLite.encode_field(:x, "x", type: :temporal, title: "年月")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "支出金額")
```

![choco_graph_manth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/221df28c-e2f7-6f17-587d-6d6da4a35552.png)

かなり規則的な周期が見えます

各年に分けて、何月が毎年ピークになっているのか見てみましょう（見なくても分かるとは思いますが）

```elixir
2015..2022
|> Enum.map(fn year ->
  df = DataFrame.filter(choco_df, 年 == ^year)

  month = Series.to_list(df["月"])
  expenses = Series.to_list(df["支出金額"])

  graph =
    VegaLite.new(width: 700, title: "チョコレート支出金額推移")
    |> VegaLite.data_from_values(x: month, y: expenses)
    |> VegaLite.mark(:line, tooltip: true)
    |> VegaLite.encode_field(:x, "x", type: :ordinal, title: "月")
    |> VegaLite.encode_field(:y, "y",
      type: :quantitative,
      title: "支出金額",
      scale: [domain: [0, 1500]]
    )

  {year, graph}
end)
|> Kino.Layout.tabs()
```

![choco_graph_per_year.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/68a7aa15-48dc-bec6-758d-279bcf1ac763.gif)

毎年2月にピークを迎え、暑くなると落ち込んでいます

日本のチョコレート市場は明確にバレンタインに依存しています

また、新型コロナウィルスの影響が僅かに見て取れます

WHOのパンデミック宣言が2020年3月11日なので、2020年までのバレンタインに比べて、2021年、2022年のバレンタインの盛り上がりは控えめになっています

## 年次推移

では年次推移を見てみましょう

支出金額を年単位で集約します

```elixir
year_choco_df =
  choco_df
  |> DataFrame.group_by("年")
  |> DataFrame.summarise(
    最小: min(支出金額),
    最大: max(支出金額),
    平均: mean(支出金額),
    合計: sum(支出金額)
  )

Kino.DataTable.new(year_choco_df)
```

![choco_sum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/7a6b437d-f8be-f128-4ee2-a4a6e21c0175.png)

直観的に分かるようにグラフ化してみます

まず合計の年次推移を見ます

```elixir
year = Series.to_list(year_choco_df["年"])
expenses = Series.to_list(year_choco_df["合計"])

VegaLite.new(width: 700, title: "チョコレート年間支出金額推移")
|> VegaLite.data_from_values(x: year, y: expenses)
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :ordinal, title: "年")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "合計支出金額")
```

![choco_graph_sum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/d6d59d54-c8cb-6012-c2d8-3e6d28bf0ab0.png)

合計支出金額は 2015年から2019年に上昇し、その後停滞もしくは微減しています

最小、最大、平均の推移も見てみましょう

各統計項目を重ねてグラフ化したいので、 `DataFrame.pivot_longer` でデータフレームの形を変えます

```elixir
pivot_table =
  DataFrame.pivot_longer(
    year_choco_df,
    ["最小", "最大", "平均"],
    names_to: "統計項目",
    values_to: "統計値"
  )

Kino.DataTable.new(pivot_table)
```

![choco_pivot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/49a2473d-86f2-c4dc-9179-f41d4f4de76d.png)

統計項目を色として、3種類の統計値を重ねて表示します

```elixir
year = Series.to_list(pivot_table["年"])
items = Series.to_list(pivot_table["統計項目"])
values = Series.to_list(pivot_table["統計値"])

VegaLite.new(width: 700, title: "チョコレート年間支出金額推移")
|> VegaLite.data_from_values(x: year, items: items, values: values)
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :ordinal, title: "年")
|> VegaLite.encode_field(:y, "values", type: :quantitative, title: "支出金額")
|> VegaLite.encode_field(:color, "items")
```

![choco_graph_min_max_mean.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/0c9b7e1a-e430-ffe7-9995-b44dc5452174.png)

これを見ると、2021年に最大がガクッと下がったのに対して、最小や平均は下がっていないことが分かります

つまり、バレンタインのようなイベントに集中して消費されていたのが、近年では年間通して食べられるようになったわけです

「チョコレート効果」や「GABA」のような健康志向の商品の売れ行きが好調のようです

https://diamond-rm.net/sales-promotion/81696/3/

https://www.meiji.co.jp/sweets/chocolate/chocokoka/?gclid=Cj0KCQiArsefBhCbARIsAP98hXQDa6nYKUWsk28ULj4YyR4yuYFPnEcHw0Pgyyys67490ZppkxLfPcwaAkmZEALw_wcB

https://www.glico.com/jp/product/chocolate/gaba/40921/

## 菓子類内訳

では、菓子類全体の中でチョコレートはどれくらいの割合を占めているのでしょうか

大分類1、中分類8の菓子類データを抽出します

```elixir
snack_df =
  DataFrame.filter(
    household_df,
    大分類 == "1" and
      中分類 == "8" and
      符号 != "-"
  )

Kino.DataTable.new(snack_df)
```

2022年12月時点の菓子類の各品目を支出金額の高い順に並べてみましょう

```elixir
latest_snack_df = DataFrame.filter(snack_df, 年 == 2022 and 月 == 12)

items = Series.to_list(latest_snack_df["品目分類"])
expenses = Series.to_list(latest_snack_df["支出金額"])

VegaLite.new(width: 700, title: "菓子類支出金額")
|> VegaLite.data_from_values(x: items, y: expenses)
|> VegaLite.mark(:bar, tooltip: true)
|> VegaLite.encode_field(:x, "x", type: :nominal, title: "品目分類", sort: "-y")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "支出金額")
```

![snack_bar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/4d051d40-7e05-dcd0-7700-ee8c5d5e2bb5.png)

他の菓子が圧倒的に多いですが、品目単体として見ると以下の順になっています

- 1位: ケーキ
- 2位: チョコレート
- 3位: せんべい

支出金額で見ているため、単価の高いケーキが1位なのは納得です

そういった中、2位につけているチョコレートは素晴らしいと言えます

円グラフでも見てみましょう

```elixir
VegaLite.new(title: "菓子類支出金額")
|> VegaLite.data_from_values(x: items, y: expenses)
|> VegaLite.mark(:arc, inner_radius: 50, tooltip: true)
|> VegaLite.encode_field(:color, "x", type: :nominal, title: "品目分類")
|> VegaLite.encode_field(:theta, "y", type: :quantitative, title: "支出金額")
```

![snack_arc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/7811dea3-e337-2d17-c65f-11c8ea0bc36b.png)

ケーキの割合がかなり高いことが分かります

しかし、チョコレートもチョコレート菓子を合わせれば中々のものです

「チョコレート」と「チョコレート菓子」の違いはグリコが教えてくれます

https://www.glico.com/jp/customer/qa/2585/

例を挙げると、以下のように分かれています

- チョコレート
  - 明治ミルクチョコレート
  - 森永ミルクチョコレート
  - ガーナチョコレート
  - ルックチョコレート
  - DARS
  - 紗々

- チョコレート菓子
  - きのこの山
  - たけのこの里
  - コアラのマーチ
  - トッポ
  - ポッキー
  - チョコボール

菓子類全体の支出金額推移を見てみましょう

```elixir
total_snack_df =
  DataFrame.filter(
    household_df,
    大分類 == "1" and
      中分類 == "8" and
      符号 == "-"
  )

Kino.DataTable.new(total_snack_df)
```

```elixir
month = Series.to_list(total_snack_df["年月"])
expenses = Series.to_list(total_snack_df["支出金額"])

VegaLite.new(width: 700, title: "菓子類支出金額推移")
|> VegaLite.data_from_values(x: month, y: expenses)
|> VegaLite.mark(:line, tooltip: true)
|> VegaLite.encode_field(:x, "x", type: :temporal, title: "年月")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "支出金額")
```

![snack_graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/9f7ea6fa-77ab-c62d-c6db-4027f8f13c0d.png)

周期的に突出しているのは12月で、ケーキのクリスマス特需です

何となく、菓子類全体では上昇傾向になっていそうですね

では、菓子類全体に占めるチョコレートの割合=チョコレート率を見てみましょう

ついでにチョコレート菓子率と、チョコレートとの合計でチョコレート類率も算出します

```elixir
choco_snack_df = DataFrame.filter(household_df, 符号 == "353")

ratio_df =
  total_snack_df[["年月", "支出金額"]]
  |> DataFrame.join(
    choco_df[["年月", "支出金額"]],
    on: ["年月"]
  )
  |> DataFrame.rename(["年月", "菓子類合計", "チョコレート"])
  |> DataFrame.join(
    choco_snack_df[["年月", "支出金額"]],
    on: ["年月"]
  )
  |> DataFrame.rename(["年月", "菓子類合計", "チョコレート", "チョコレート菓子"])
  |> DataFrame.mutate(
    チョコレート率: チョコレート / 菓子類合計,
    チョコレート菓子率: チョコレート菓子 / 菓子類合計
  )
  |> DataFrame.mutate(チョコレート類率: チョコレート率 + チョコレート菓子率)
  |> DataFrame.pivot_longer(
    &String.ends_with?(&1, "率"),
    names_to: "品目",
    values_to: "占有率"
  )

Kino.DataTable.new(ratio_df)
```

チョコレート率の推移をグラフ化します

```elixir
month = Series.to_list(ratio_df["年月"])
items = Series.to_list(ratio_df["品目"])
ratio = Series.to_list(ratio_df["占有率"])

VegaLite.new(width: 600, title: "占有率推移")
|> VegaLite.data_from_values(x: month, y: ratio, color: items)
|> VegaLite.mark(:line, tooltip: true)
|> VegaLite.encode_field(:x, "x", type: :temporal, title: "年月")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "占有率")
|> VegaLite.encode_field(:color, "color")
```

![choco_ratio_graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/e974548b-93d5-1a6e-4a18-85ec2787cf42.png)

チョコレート菓子はそこまでバレンタインに依存していないことが分かります

チョコレート類率の最大値は2017年2月の 23.2% でした

こうして見ると、チョコレート類率はコロナ以前、2018年から減少傾向にありそうです

では菓子類全体の年次推移を見てみましょう

```elixir
year_total_snack_df =
  total_snack_df
  |> DataFrame.group_by("年")
  |> DataFrame.summarise(合計: sum(支出金額))

Kino.DataTable.new(year_total_snack_df)
```

```elixir
year = Series.to_list(year_total_snack_df["年"])
expenses = Series.to_list(year_total_snack_df["合計"])

VegaLite.new(width: 700, title: "菓子類年間支出金額推移")
|> VegaLite.data_from_values(x: year, y: expenses)
|> VegaLite.mark(:line, tooltip: true)
|> VegaLite.encode_field(:x, "x", type: :ordinal, title: "年")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "合計支出金額")
```

![snack_line.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/2fd77895-389b-1c7b-f357-15de8be3fce9.png)

なんと、菓子類全体はコロナで下がるどころか上がっています

巣篭もり需要と値上げが要因でしょうか

チョコレート率の年次推移を見てみます

```elixir
year_choco_snack_df =
  choco_snack_df
  |> DataFrame.group_by("年")
  |> DataFrame.summarise(合計: sum(支出金額))

year_ratio_df =
  year_total_snack_df[["年", "合計"]]
  |> DataFrame.join(
    year_choco_df[["年", "合計"]],
    on: ["年"]
  )
  |> DataFrame.rename(["年", "菓子類合計", "チョコレート"])
  |> DataFrame.join(
    year_choco_snack_df[["年", "合計"]],
    on: ["年"]
  )
  |> DataFrame.rename(["年", "菓子類合計", "チョコレート", "チョコレート菓子"])
  |> DataFrame.mutate(
    チョコレート率: チョコレート / 菓子類合計,
    チョコレート菓子率: チョコレート菓子 / 菓子類合計
  )
  |> DataFrame.mutate(チョコレート類率: チョコレート率 + チョコレート菓子率)
  |> DataFrame.pivot_longer(
    &String.ends_with?(&1, "率"),
    names_to: "品目",
    values_to: "占有率"
  )

Kino.DataTable.new(year_ratio_df)
```

```elixir
year = Series.to_list(year_ratio_df["年"])
items = Series.to_list(year_ratio_df["品目"])
ratio = Series.to_list(year_ratio_df["占有率"])

VegaLite.new(width: 600, title: "占有率推移")
|> VegaLite.data_from_values(x: year, y: ratio, color: items)
|> VegaLite.mark(:line, tooltip: true)
|> VegaLite.encode_field(:x, "x", type: :ordinal, title: "年")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "占有率")
|> VegaLite.encode_field(:color, "color")
```

![choco_ratio_year_graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/3ab8dbd6-86c3-d1e0-902a-c0b1688cc59c.png)

チョコレート率はやはりコロナの影響が大きく、菓子類全般の伸びには追従できていないようですが、チョコレート菓子率が伸びています

チョコレート菓子は元からバレンタインの影響が少なく、焼きチョコなどの夏でも食べやすい商品もあります

ただし、支出金額なので値上げの影響も考えられます

元から安かったチョコレート菓子の場合、数円の値上げが大きく影響します

https://toyokeizai.net/articles/-/647460

多少値上げしてもブラックサンダー愛好家は買い続けますが、ちょっと贅沢なチョコレートは買い控えるようになったのかもしれません

## まとめ

総務省統計局のデータを見ることで、チョコレートに関して様々な視点で分析することができました

とりあえずチョコレートが食べたくなりました