1920年から2015年までの都道府県別の5歳階級別人口推移

 e-Stat を渉猟していると面白いファイルを見つけた.国勢調査は 1920 年から開始されており, 2020 年 3 月現在では最新の調査結果は 2015 年のものである.20 回分の人口データが一つのファイルにまとめられており,グラフ化するには格好のデータである.

 年齢(5歳階級),男女別-都道府県(大正9年~平成27年)というファイルである.リンク先のページにはファイルが 3 つあるが,最後のものが最も粒度が細かいので,これをグラフ化する.

年齢(5歳階級),男女別人口-都道府県(大正9年~平成27年)
年齢(5歳階級),男女別人口-都道府県(大正9年~平成27年)

Power Query でデータクレンジング

 ダウンロードしたファイル (“FEI_CITY_************.csv”) を直接開かず,別の EXCEL ファイルから Power Query で開く.

 「元号」と「和暦(年)」は不要なので削除する.重要なのは西暦年である.

Power Query エディタでデータを開いたところ
Power Query エディタでデータを開いたところ

年齢5歳階級の列を観察する

 まずフィルターをポップアップしてどんなデータがあるか確認する.

年齢5歳階級のフィルターからデータを確認する
年齢5歳階級のフィルターからデータを確認する

 スクロールバーをスクロールして最下段まで見に行く.

年齢5歳階級のフィルターからデータを確認する
年齢5歳階級のフィルターからデータを確認する

「数え歳」の扱い

 5歳階級であるから範囲の数値となる.一部,1歳ずつずれている範囲がある.これは 1945 年の国勢調査にだけ見られるもので,日本人独特の「数え歳」を反映している.終戦後の混乱の中で国勢調査を実施する困難は想像に余りある.

 それはともかく,これはデータ系列を作成するには邪魔になるため,目をつぶって1歳ずらすことにする.

 上図を見ると分かるが,「空白」と「総数」は不要な行なのでチェックを外しておく.「80歳以上」「80~84歳」「85歳以上」が混乱するが,「80歳以上」の分類は国勢調査の始まったごく初期だけのものであるため,このままにしておく.

「列の分割」は「数字から数字以外による分割」

 問題は「年齢5歳階級」をどう分割するかである.適切な分割方法が既に用意されていた.「数字から数字以外による分割」できれいに先頭の数字だけを抽出できる.

「数字から数字以外による分割」
「数字から数字以外による分割」

 この段階でテーブルに読み込む.

生年は年度から年齢階級を引き算して求める

 観察する年によって値が変わるという意味で,年齢は相対値である.しかし,生年は絶対値である.世の中に数多くあるグラフは年齢で区分されていたため,経時的な推移を見るには不適切だった.むしろ生年で区分けした方が分かりやすい.

 こういう作業も EXCEL は得意である.

 まず,Mod 関数で年齢を 5 で除算した剰余を求める.次に,IF 関数で結果が 1 なら年齢から 1 を引き,そうでないなら年齢をそのまま扱う.最後に年度から IF 関数の結果を引き算して生年を求める.

 1 月から 3 月生まれの分がずれるが,これは毎年のことであり,誕生月が不明のためやむを得ないと割り切る.今後の調査で誕生月まで分かれば,さらに正確なデータからグラフを作成できるだろう.

 作業列をコピーして値を貼り付けし,参照関係を解消する.生年の列だけを残して作業列を削除する.結果を .txt ファイルに保存する.

SQL Server でデータ系列を整形

概要

 ウィザードを使って先程保存した .txt ファイルをインポートする.

 EXCEL のデータ系列の仕様に合わせてデータの枠組みを作成する.年度は 1920 年から 2015 年までの 20 件.一方,生年は 1840 年から 2015 年までの 36 件.さらに都道府県が 47 ある.これらの直積 33840 件を求める.

クエリ

 一時テーブルで生年,年度,都道府県を作成する.都道府県コードと都道府県名は先程インポートしてできたテーブルから読み込んでいる(70-71 行目).

DROP TABLE IF EXISTS #BIRTHYEAR;
CREATE TABLE #BIRTHYEAR(BirthYear int NOT NULL);

INSERT INTO #BIRTHYEAR
VALUES	 (1840)
	,(1845)
	,(1850)
	,(1855)
	,(1860)
	,(1865)
	,(1870)
	,(1875)
	,(1880)
	,(1885)
	,(1890)
	,(1895)
	,(1900)
	,(1905)
	,(1910)
	,(1915)
	,(1920)
	,(1925)
	,(1930)
	,(1935)
	,(1940)
	,(1945)
	,(1950)
	,(1955)
	,(1960)
	,(1965)
	,(1970)
	,(1975)
	,(1980)
	,(1985)
	,(1990)
	,(1995)
	,(2000)
	,(2005)
	,(2010)
	,(2015);

DROP TABLE IF EXISTS #FISCALYEAR;
CREATE TABLE #FISCALYEAR(FiscalYear int NOT NULL);

INSERT INTO #FISCALYEAR
VALUES   (1920)
	,(1925)
	,(1930)
	,(1935)
	,(1940)
	,(1945)
	,(1950)
	,(1955)
	,(1960)
	,(1965)
	,(1970)
	,(1975)
	,(1980)
	,(1985)
	,(1990)
	,(1995)
	,(2000)
	,(2005)
	,(2010)
	,(2015);

DROP TABLE IF EXISTS #PrefCode
CREATE TABLE #PrefCode(PrefCode nchar(2) NOT NULL, Prefecture nvarchar(50) NOT NULL);

INSERT INTO #PrefCode
SELECT DISTINCT PrefCode, Prefecture FROM	dbo.T_PrefPopulation1920_2015;

WITH CTE AS
(
SELECT	PrefCode, Prefecture, BirthYear, FiscalYear
FROM	#PrefCode
CROSS	JOIN #BIRTHYEAR
CROSS	JOIN #FISCALYEAR
)

SELECT	CTE.PrefCode
	,	CTE.BirthYear
	,	CTE.FiscalYear
	,	CTE.Prefecture
	,	CASE WHEN P.TotalPopulation	IS NULL THEN 0 ELSE P.TotalPopulation	END AS Total
	,	CASE WHEN P.MenPopulation	IS NULL THEN 0 ELSE P.MenPopulation	END AS Men
	,	CASE WHEN P.WomenPopulation	IS NULL THEN 0 ELSE P.WomenPopulation	END AS Women
FROM	CTE
LEFT	JOIN dbo.T_PrefPopulation1920_2015	AS P
ON	CTE.BirthYear	= P.BirthYear
AND	CTE.FiscalYear	= P.FiscalYear
AND	CTE.PrefCode	= P.PrefCode
ORDER	BY CTE.PrefCode, CTE.BirthYear, CTE.FiscalYear;

 結果をヘッダー付きでコピーし,EXCEL に貼り付ける.マクロつきブックで保存する.

EXCEL VBA でグラフ作成

概要

 人口は絶対値であるためグラフ形式は「積み上げ棒」が妥当である.ここでは男女別ではなく総数のため縦棒である(26 行目).男女別にするなら横棒となる.

 まずテーブルに都道府県コードでフィルターをかけ,結果を Range オブジェクトで取得する(33-35 行目).

 ついで生年でフィルターをかけ,結果を Range オブジェクトで取得する(39-41 行目).

 取得した Range オブジェクトから年度と総人口を取得し,配列に入力する(47-48 行目).

 Series オブジェクトを生成し,データ系列名と横軸,縦軸の値を入力する(52-56 行目).

 以上 61 行目までがグラフの骨格であり,62 行目以降はいわば「お化粧」である.

 63-67 行目でタイトルを有効化し,.Caption プロパティで都道府県名を入力し,位置を調整する.

 70-74 行目で横軸の書式を設定している.軸目盛の方向を左に 90 度傾けている.

 75-100 行目で縦軸の書式を設定している.表示単位を万とし,ラベルを削除する.境界値の最大値に応じて最大値を変更して揃え,主目盛線を 5 等分する.

 101-104 行目でグラフエリアの書式を設定し,グラフ全体のフォントを変更している.

 105-107 行目でデータ系列の間隔を 0 とし,間を詰めている.

 108-189 行目でデータ系列の色を設定する.5歳階級を連続で5回分,合計 25 年で 1 系統となるように選んでいる.結果として 1925 年生まれ,1950 年生まれ,1975 年生まれ,2000 年生まれの色が最も濃くなった.これらは日本の人口統計を議論する上で重要な年齢階級である.

コード

Option Explicit

Sub PrefPopulation()
Dim mySht1  As Worksheet
Dim mySht2  As Worksheet
Dim LstObj  As ListObject
Dim myCht   As Chart

Set mySht1 = Worksheets("Sheet1")
Set mySht2 = Worksheets.Add
Set LstObj = mySht1.ListObjects(1)

Dim i       As Long
Dim j       As Long
Dim myRng1  As Range
Dim myRng2  As Range
Dim k       As Long

Dim FiscalYear()    As Long
Dim Population()    As Long
Dim mySeries        As Series

Dim myAxis  As Axis

For i = 1 To 47
    Set myCht = mySht2.Shapes.AddChart2(Style:=-1, _
                                  XlChartType:=xlColumnStacked, _
                                         Left:=200 * ((i - 1) Mod 6), _
                                          Top:=200 * ((i - 1) \ 6), _
                                        Width:=200, _
                                       Height:=200).Chart
    With LstObj
        .Range.AutoFilter field:=1, Criteria1:=i
        Set myRng1 = Intersect(.DataBodyRange, _
                               .Range.SpecialCells(Type:=xlCellTypeVisible))
        If myRng1 Is Nothing Then
        Else
            For j = 2015 To 1845 Step -5
                .Range.AutoFilter field:=2, Criteria1:=j
                Set myRng2 = Intersect(.DataBodyRange, _
                                       .Range.SpecialCells(Type:=xlCellTypeVisible))
                If myRng2 Is Nothing Then
                Else
                    For k = 0 To myRng2.Rows.Count - 1
                        ReDim Preserve FiscalYear(k)
                        ReDim Preserve Population(k)
                        FiscalYear(k) = myRng2.Cells(k + 1, 3)
                        Population(k) = myRng2.Cells(k + 1, 5)
                    Next k
                End If
                .Range.AutoFilter field:=2
                Set mySeries = myCht.SeriesCollection.NewSeries
                With mySeries
                    .Name = j
                    .XValues = FiscalYear
                    .Values = Population
                End With
            Next j
        End If
        .Range.AutoFilter field:=1
    End With
    With myCht
        .HasTitle = True
        With .ChartTitle
            .Caption = myRng2.Cells(1, 4)
            .Left = 0
            .Top = 0
        End With
        Set myAxis = .Axes(xlCategory)
        With myAxis
            .Format.Line.Visible = msoFalse
            .MajorGridlines.Format.Line.Visible = msoFalse
            .TickLabels.Orientation = xlUpward
        End With
        Set myAxis = .Axes(xlValue)
        With myAxis
            .DisplayUnit = xlTenThousands
            .DisplayUnitLabel.Delete
            Select Case .MaximumScale
                Case 0 To 1000000
                .MaximumScale = 1000000
                Case 1000001 To 1250000
                .MaximumScale = 1250000
                Case 1250001 To 1500000
                .MaximumScale = 1500000
                Case 1500001 To 2500000
                .MaximumScale = 2500000
                Case 2500001 To 5000000
                .MaximumScale = 5000000
                Case 5000001 To 10000000
                .MaximumScale = 10000000
                Case 10000001 To 12500000
                 .MaximumScale = 12500000
                Case 12500001 To 15000000
                 .MaximumScale = 15000000
            Case Else
            End Select
            .MajorUnit = .MaximumScale / 5
            .MajorGridlines.Format.Line.Visible = msoFalse
        End With
        With .ChartArea
            .Format.Fill.ForeColor.ObjectThemeColor = msoThemeColorBackground1
            .Format.TextFrame2.TextRange.Font.Name = "TimesNewRoman"
        End With
        With .ChartGroups(1)
            .GapWidth = 0
        End With
        For Each mySeries In .SeriesCollection
            With mySeries
                Select Case .Name
                Case "2020"
                .Format.Fill.ForeColor.RGB = RGB(218, 227, 243)
                Case "2015"
                .Format.Fill.ForeColor.RGB = RGB(180, 199, 231)
                Case "2010"
                .Format.Fill.ForeColor.RGB = RGB(143, 170, 220)
                Case "2005"
                .Format.Fill.ForeColor.RGB = RGB(47, 85, 151)
                Case "2000"
                .Format.Fill.ForeColor.RGB = RGB(32, 56, 100)
                Case "1995"
                .Format.Fill.ForeColor.RGB = RGB(226, 240, 217)
                Case "1990"
                .Format.Fill.ForeColor.RGB = RGB(197, 224, 180)
                Case "1985"
                .Format.Fill.ForeColor.RGB = RGB(169, 209, 142)
                Case "1980"
                .Format.Fill.ForeColor.RGB = RGB(84, 130, 53)
                Case "1975"
                .Format.Fill.ForeColor.RGB = RGB(56, 87, 35)
                Case "1970"
                .Format.Fill.ForeColor.RGB = RGB(255, 242, 204)
                Case "1965"
                .Format.Fill.ForeColor.RGB = RGB(255, 230, 153)
                Case "1960"
                .Format.Fill.ForeColor.RGB = RGB(255, 217, 102)
                Case "1955"
                .Format.Fill.ForeColor.RGB = RGB(191, 144, 0)
                Case "1950"
                .Format.Fill.ForeColor.RGB = RGB(127, 96, 0)
                Case "1945"
                .Format.Fill.ForeColor.RGB = RGB(251, 229, 214)
                Case "1940"
                .Format.Fill.ForeColor.RGB = RGB(248, 203, 173)
                Case "1935"
                .Format.Fill.ForeColor.RGB = RGB(244, 177, 131)
                Case "1930"
                .Format.Fill.ForeColor.RGB = RGB(197, 90, 17)
                Case "1925"
                .Format.Fill.ForeColor.RGB = RGB(132, 60, 12)
                Case "1920"
                .Format.Fill.ForeColor.RGB = RGB(242, 242, 242)
                Case "1915"
                .Format.Fill.ForeColor.RGB = RGB(217, 217, 217)
                Case "1910"
                .Format.Fill.ForeColor.RGB = RGB(191, 191, 191)
                Case "1905"
                .Format.Fill.ForeColor.RGB = RGB(166, 166, 166)
                Case "1900"
                .Format.Fill.ForeColor.RGB = RGB(127, 127, 127)
                Case "1895"
                .Format.Fill.ForeColor.RGB = RGB(242, 242, 242)
                Case "1890"
                .Format.Fill.ForeColor.RGB = RGB(217, 217, 217)
                Case "1885"
                .Format.Fill.ForeColor.RGB = RGB(191, 191, 191)
                Case "1880"
                .Format.Fill.ForeColor.RGB = RGB(166, 166, 166)
                Case "1875"
                .Format.Fill.ForeColor.RGB = RGB(127, 127, 127)
                Case "1870"
                .Format.Fill.ForeColor.RGB = RGB(242, 242, 242)
                Case "1865"
                .Format.Fill.ForeColor.RGB = RGB(217, 217, 217)
                Case "1860"
                .Format.Fill.ForeColor.RGB = RGB(191, 191, 191)
                Case "1855"
                .Format.Fill.ForeColor.RGB = RGB(166, 166, 166)
                Case "1850"
                .Format.Fill.ForeColor.RGB = RGB(127, 127, 127)
                Case "1845"
                .Format.Fill.ForeColor.RGB = RGB(242, 242, 242)
                Case "1840"
                .Format.Fill.ForeColor.RGB = RGB(217, 217, 217)
                Case "1835"
                .Format.Fill.ForeColor.RGB = RGB(191, 191, 191)
                End Select
            End With
        Next mySeries
    End With
Next i

End Sub

結果

 都道府県によって人口動態が異なるが,全体を俯瞰してみると,やはり第2次世界大戦により東京と大阪,沖縄の人口が激減しているのがまず目に止まる.

 1925 年生まれは終戦時 20 歳から 25 歳にあたり,戦場に駆り出されたと考えられる.他にも疎開で地方に移動した人口もある.1945 年人口が突出している県はおそらく疎開の影響である.

 1950 年代生まれは第1次ベビーブーム世代にあたる.この世代は団塊世代と呼ばれ,高齢化して社会の重荷となりつつある.

 1975 年生まれは団塊ジュニア世代と呼ばれ,20 年後には社会の重荷と言われるようになる.理由は様々であるが,就職氷河期世代とも呼ばれ,十分な資本蓄積が進まなかった影響が大きい.

 2000 年生まれは第3次ベビーブーム世代とはならなかった.団塊ジュニア世代が結婚せず,子供を作らなかったためである.

1920年から2015年までの都道府県別の5歳階級別人口推移
1920年から2015年までの都道府県別の5歳階級別人口推移

まとめ

 総務省の「1920年から2015年までの都道府県別の5歳階級別人口推移」のファイルから,都道府県別の5歳階級別人口推移のグラフを作成した.

 国勢調査から作成された人口動態グラフは数多く存在するが,生年で年齢階級を分類したグラフは見たことがない.

 分類法を変更するだけで複雑なデータが分かりやすくなる.これもデータビジュアライゼーションの一例である.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください