5
1

Rの初心者向け記事でもあります。

書いた動機

・色々言われるふるさと納税について、面白い分析がもっと増えてほしい
・特にSNSでは肯定派/否定派ともに「●×に決まっている」「●×なのは明らか」と言った断定口調の割に数理的な根拠が乏しいことが多い
・願わくば生まれが地方で現住所が都市部の自分としては、マクロで役に立つ制度であってほしい
という願望から生まれました。

使用するデータ

全てオープンデータです。
検索するのが面倒だったり、データの中のどこを使えばよいか困ったりするので、備忘録がてら残します。

注意
年度によってデータ形式が異なる場合があります。

①各自治体のふるさと納税の流入額
https://www.soumu.go.jp/main_sosiki/jichi_zeisei/czaisei/czaisei_seido/furusato/archive/
>令和5年度ふるさと納税に関する現況調査について
>各自治体のふるさと納税受入額及び受入件数(平成20年度~令和4年度) ←このExcel
000894504.xlsx
↓一部
流入額.png
ヘッダー部分に注意書きがあったり多重構造になっているので前処理が必要です。(どこを使ったかは後のコード参照、以下同じ)

今回は流入額のみをピックアップしますが、「経費構造がどうなっているか」「納税する際の用途指定」「具体的に使ったこと」なども記載されています。
こちらも眺めてみると何か見つかるかもしれません。

②流出額
同じく①の下にある
>令和5年度課税における住民税控除額の実績等 ←このExcel
000897134.xlsx
↓一例
流出額.png
こちらも流入額と同じような構成になっています。
政府もe-Statに力を入れて改善を進めてくれているので、分析側が使いやすいデータ構造で公開するのを祈ります。(あと検索性能が上がるともっと嬉しいです)

但し流出額側には市区町村団体コードがありませんので、流入額とは「都道府県名」「市区町村名」で結合します。

③自治体の人口
https://www.soumu.go.jp/main_sosiki/jichi_gyousei/daityo/jinkou_jinkoudoutai-setaisuu.html
>【総計】令和5年住民基本台帳年齢階級別人口(市区町村別) ←このExcel
000892953.xlsx
↓一例
人口.png
今回は総計しか使いませんので別のデータでも構いません。
例えば子ども一人あたり、高齢者一人あたり…で何かを見たいときはこのような年齢階層データが役立ちそうです。

因みにこちらのデータを流入額と結合する際は、都道府県名・市区町村名ではなく団体コードで結合します。
→ふるさと納税の方は町村名が「●●町」だけなのに対し、こちらのデータでは「▲▲郡●●町」なので結合に失敗するため。町村だけ値がおかしくて何かと思ったら罠がありました

④自治体の平均年収
https://www.soumu.go.jp/main_sosiki/jichi_zeisei/czaisei/czaisei_seido/ichiran09_22.html
>第11表 課税標準額段階別令和4年度分所得割額等に関する調(合計)
 (所得割納税義務者数・課税対象所得・課税標準額・所得割額) ←このExcel
J51-22-b.xlsx
↓一例
image.png
やった、ヘッダーが一行目に…あるけどない!(泣)

こちらも市区町村コードがあるので結合に使います。
※蛇足ながらこのデータも町村の名前に郡は付きません。全部総務省なのになぜ…

以上の4つを使います。

使用するライブラリ

R
library(tidyverse)
library(openxlsx)
library(ggrepel)
library(scales)

openxlsx...Excelを使うため
ggrepel...散布図でプロットされたデータにラベルを付けるため
scales...ggplotのグラフの縦横軸のスケールを変えるため
    例) comma_format(千の桁でコンマ区切り)、percent_format(%表示)など

データ読み込み

入力データである各Excelは、r/rmdファイルと同じ階層のinputフォルダに入れています。

R
# 流入額
df_inflow <- read.xlsx(".\\input\\000894504.xlsx",
                       startRow = 13)

# 1,2,3列目が自治体コード、都道府県名、自治体名
# 6,7列目が流入件数と額
df_inflow <- df_inflow[, c(1,2,3,6,7)]

colnames(df_inflow) <- c("Code", "Prefecture", "Name", "InflowCount", "InflowAmount")

# 流出額
df_outflow <- read.xlsx(".\\input\\000897134.xlsx",
                       startRow = 18)

# 1,2列目が都道府県名、自治体名
# 54,56列目が人数と流出額
df_outflow <- df_outflow[, c(1,2,54,56)]
colnames(df_outflow) <- c("Prefecture", "Name", "OutflowPeople", "OutflowAmount")

# 結合する
df_input <- left_join(df_inflow, df_outflow,
                       by = c("Prefecture", "Name"))

# 都道府県は除外
df_input <- df_input %>% 
  filter(!is.na(Name))

# 人口関連
df_population <- read.xlsx(".\\input\\000892953.xlsx",
                       startRow = 3)

# 5列目が総数で、10~17列目が20歳以上
df_population$PopulationTtl <- df_population[, c(5)]

# 年代ごとの人数は削除
df_population <- df_population[, c("団体コード", "都道府県名", "市区町村名", "性別",
                                   "PopulationTtl")]

# 性別は合計のみかつ自治体のみにする
df_population <- df_population %>% 
  rename(Code = 団体コード,
         Prefecture = 都道府県名,
         Name = 市区町村名,
         Sex = 性別) %>% 
  select(Code, Prefecture, Name, Sex, PopulationTtl) %>% 
  filter(Sex == "計",
           Name != "-") %>% 
  select(-Sex)

# 人口も結合。但し市区町村名がふるさと納税の構成と異なるので、Codeでつなぐ
df_input <- left_join(df_input, df_population %>% select(-Prefecture, -Name),
                       by = c("Code"))

# 自治体住人の平均収入や納税者数
df_income <- read.xlsx(".\\input\\J51-22-b.xlsx",
                       startRow = 3)

# 2,3,4列目が自治体コード、都道府県名、自治体名
# 5列目が市町村税か都道府県税か
# 6,14列目が納税者数と課税対象所得合計
df_income <- df_income[, c(2,3,4,5,6,14)]

colnames(df_income) <- c("Code", "Prefecture", "Name", "TaxType", "TaxPayers", "IncomeAmount")

df_income <- df_income %>% 
  mutate(AvrIncome = IncomeAmount / TaxPayers * 1000) %>% 
  filter(TaxType == "市町村民税") %>% 
  select(-TaxType)

# 課税関連も結合。但し市区町村名がふるさと納税の構成と異なるので、Codeでつなぐ
df_input <- left_join(df_input, df_income %>% select(-Prefecture, -Name),
                       by = c("Code"))

# ふるさと納税の流出入の差額
# ふるさと納税の一人あたりの控除額
# ふるさと納税の一人あたりの流入額(こちらも住人数ではなく、制度利用者数に対し)
# 納税者に対して、一人あたりの流出額
# 納税者に対して、どのくらいの割合でふるさと納税をやっているか
# 住民一人あたりの差額
df_input <- df_input %>% 
  mutate(DefAmount = InflowAmount - OutflowAmount,
         PerCapitaOutflow = OutflowAmount / OutflowPeople,
         PerCapitaInflow = InflowAmount / OutflowPeople,
         PerTaxPayersOutflow = OutflowAmount / TaxPayers,
         OutflowTaxPayersRatio = OutflowPeople / TaxPayers,
         PerPopDefOutflow = DefAmount / PopulationTtl)

# 都道府県ごとの表示をするためのでマージ。但し一人あたりのものは再計算
df_input_pref <- df_input %>% 
  select(-Code, -Name) %>% 
  group_by(Prefecture) %>% 
  summarize(across(everything(), sum)) %>% 
  mutate(DefAmount = InflowAmount - OutflowAmount,
         PerCapitaOutflow = OutflowAmount / OutflowPeople,
         PerCapitaInflow = InflowAmount / OutflowPeople,
         PerTaxPayersOutflow = OutflowAmount / TaxPayers,
         OutflowTaxPayersRatio = OutflowPeople / TaxPayers,
         PerPopDefOutflow = DefAmount / PopulationTtl)

前処理が終わったら後はグラフ化するだけです。
たまに報道に対して、
・数を出してきたら割合を見る
・割合を出してきたら数を見る
という声が挙げられます。気になったところはぜひご自分で確認ください。

可視化例

・住人一人あたりの流出額
総額で横浜市、大阪市、川崎市あたりが多いのは言われているので、一人あたりで見てみます。

R
ggplot(df_input %>% 
         arrange(desc(PerPopDefOutflow)) %>% 
         tail(20),
       aes(x = PerPopDefOutflow,
           y = reorder(x = paste0(Prefecture, ":", Name), X = PerPopDefOutflow),
           fill = Prefecture)) +
  geom_col() +
  labs(title = "住人一人あたりの流出額(Top20)",
       x = "流出額[円]", y = "自治体", fill = "") +
  scale_x_continuous(labels = comma_format()) +
  geom_text(aes(label = comma(round(PerPopDefOutflow, digits = 0))),
            vjust = 0.5, x = 0, hjust = 1)

住人一人あたりの流出額.png
圧巻の東京都寡占状態ですね。

・住人一人あたりの流入額
そもそもたくさん入るところだとどのくらい入ってくるのでしょうか?

R
ggplot(df_input %>% 
         arrange(desc(PerPopDefOutflow)) %>% 
         head(20),
       aes(x = PerPopDefOutflow,
           y = reorder(x = paste0(Prefecture, ":", Name), X = PerPopDefOutflow),
           fill = Prefecture)) +
  geom_col() +
  labs(title = "住人一人あたりの流入額(Top20)",
       x = "流出額[円]", y = "自治体", fill = "") +
  scale_x_continuous(labels = comma_format()) +
  geom_text(aes(label = comma(round(PerPopDefOutflow, digits = 0))),
            vjust = 0.5, x = 0, hjust = 0)

住人一人あたりの流入額.png
8道県でほとんどは町村です。
紋別市と根室市は人口がそれぞれ2.3万人、2.7万人であり、町の人口順だと上位10~15%くらいに位置する感じです。(ディスってないです!)

ふるさと納税に依存しすぎは怖いですが、市町村民一人あたりで数十万円税収が増えると何かしらできるのではとは思います。

・人口と住人一人あたりの流出入額
ふるさと納税に対する批判で、「人口が少ない地域からも流出して本来の意図とは異なっている」と言うものがあります。
そこで人口に対して住人一人あたりの流出入がどうかを確認します。

R
ggplot(df_input %>% 
         mutate(Type = if_else(DefAmount > 0, "流入", "流出")),
       aes(x = PopulationTtl,
           y = PerPopDefOutflow,
           color = Type)) +
  geom_point() +
  labs(title = "自治体の人口と住人一人あたりの流出入額",
       x = "人口", y = "一人あたり流出入額[円]") +
  scale_x_log10(labels = comma_format()) +
  scale_y_continuous(labels = comma_format(),
                     limits = c(-50000, 500000), breaks = seq(-50000, 500000, by = 50000))

人口と住人一人あたりの流出入額.png
※横軸は対数注意。見やすさのため流入金額が極端に大きい自治体は除外

グラフを見る限りでは、人口の少ない側の地域は殆どが流入超過です。
また人口の多い側が巻き上げているかと言うと、そうでもなさそうです。

・自治体の平均年収と流出入額
他には「金持ちだけが得をする制度」と言う批判もあります。
そこで自治体住人の平均年収と制度の実施率と、制度を使っている人の一人あたりの金額を見てみます。

R
ggplot(df_input %>% 
         arrange(desc(AvrIncome)),
       aes(x = AvrIncome,
           y = OutflowTaxPayersRatio,
           label = paste0(Name, ":", round(PerCapitaOutflow / 1000, digits = 0), "千円"))) +
  geom_point() +
  geom_text_repel(force = 6) +
  labs(title = "自治体住人の平均年収と納税者のふるさと納税実施率",
       x = "平均年収[円]", y = "実施率[%]") +
  scale_x_continuous(labels = comma_format(),
                     limits = c(0, 15000000)) +
  scale_y_continuous(labels = percent_format()) +
  theme(legend.position = "none")

自治体の平均年収とふるさと納税実施率_金額付き.png
基本的には年収が高くなるほど実施率は高くなりますし、また金額も大きくなります。
港区だと制度を使っている人は一人あたり13万円強の返礼品が貰えるということで、これは確かに批判の通りとも言えます。
とはいえ流出した金額が地方に流れているとも言えそうなので、「不公平ではあるが制度の理念通りには機能している」とも言えそうで何とも悩ましいです。

逆に平均年収が低い(主に経済が活発ではないand/or高齢化率の高い地方と思われる)だと、制度の使用率も低く金額も高くはありません。

「都会がふるさと納税を活発化させて、地方から金を巻き上がる事態になっても文句言うなよ」という批判意見もありますが、「都心の●×区に5万円寄付すると有名ホテルに泊まれる」みたいなプランを利用するのは、地方の住人ではなくふるさと納税の余力のある近隣区民かもしれません。

まとめ

・折角の制度なのでマクロで日本が良くなるといいですね(願望
・enjoy R!

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1