アルゴリズムの基礎: クイックソート
クイックソート
フローチャートは、以下の本を参考に作成しました。
丁寧な解説は上記の本など参考してもらうとして、 クイックソートの基本方針は以下のとおりです。
- 手前から基準値よりも大きい値をさがす
- 後ろから基準値よりも小さい値をさがす
- それらを交換する
フローチャート
上記の基本方針をもとに、実行されています。 また、最後に基準値を正しい場所に移動する処理も追加しています。

import random
N = 9
# get random array
arr = list(range(1, N+1))
random.shuffle(arr)
print("inital array: {0}".format(arr))
# initial value
left = 0
right = N -1
def quick_sort(arr, left, right):
i = left + 1
k = right
_ref_value = arr[left] # reference value
_tmp = None
print("start: left={0}, right={1}, arr[left:right+1]={2}".format(left, right, arr[left:right+1]))
print("\t _ref_value={0}".format(_ref_value))
while (i < k):
# looking for a value bigger than _ref_value
while (arr[i] < _ref_value and i < right):
i = i + 1
# looking for a value smaller than _ref_value
while (arr[k] >= _ref_value and left < k):
k = k - 1
if (i < k):
print("\t i={0}, arr[i]={1}, k={2}, arr[k]={3}".format(i, arr[i], k, arr[k]))
_tmp = arr[i]
arr[i] = arr[k]
arr[k] = _tmp
# replace refrence value
if (arr[left] > arr[k]):
_tmp = arr[left]
arr[left] = arr[k]
arr[k] = _tmp
print("\t left={0}, arr[left] = {1}, k={2}, arr[k]={3}".format(left, arr[left], k, arr[k]))
print("\t result: {0}".format(arr))
quick_sort(arr, left, right)
以下、実行例です。 実行すると、基準値5を境にして、[3,4,1,2], [5], [7,8,9,6]のようにソートされます。
inital array: [5, 4, 8, 7, 3, 2, 1, 9, 6] start: left=0, right=8, arr[left:right+1]=[5, 4, 8, 7, 3, 2, 1, 9, 6] _ref_value=5 i=2, arr[i]=8, k=6, arr[k]=1 i=3, arr[i]=7, k=5, arr[k]=2 left=0, arr[left] = 3, k=4, arr[k]=5 result: [3, 4, 1, 2, 5, 7, 8, 9, 6]
最後にarr[k]に基準値を入れています。 そのため、以下の図のようになっています。
- [left, k-1]は基準値よりも小さい値の配列
- kの位置には実行時に決定された基準値
- [k+1, right]は基準値よりも大きい値の配列
しかし、基準値以外は正しく順番にソートされていません。 残りの部分に対して、正しくソートするために、再び[left, k-1]および[k+1, right]の 配列に対して、上記の操作を再帰的に行う必要があります。

再帰的に実行
quick_sort()を再帰的に実行して、全体をソートします。 以下のフローチャートにて、オレンジ部分が新たに追加した箇所です。
このように再帰的に呼び出しを行うことで、配列のすべての値が正しくソートされるようになります。

pythonでの実装例を示します。
import random
N = 9
# get random array
arr = list(range(1, N+1))
random.shuffle(arr)
print("inital array: {0}".format(arr))
# initial value
left = 0
right = N -1
def quick_sort(arr, left, right):
i = left + 1
k = right
_ref_value = arr[left] # reference value
_tmp = None
print("start: left={0}, right={1}, arr[left:right+1]={2}".format(left, right, arr[left:right+1]))
print("\t _ref_value={0}".format(_ref_value))
while (i < k):
# looking for a value bigger than _ref_value
while (arr[i] < _ref_value and i < right):
i = i + 1
# looking for a value smaller than _ref_value
while (arr[k] >= _ref_value and left < k):
k = k - 1
if (i < k):
print("\t i={0}, arr[i]={1}, k={2}, arr[k]={3}".format(i, arr[i], k, arr[k]))
_tmp = arr[i]
arr[i] = arr[k]
arr[k] = _tmp
# replace refrence value
if (arr[left] > arr[k]):
_tmp = arr[left]
arr[left] = arr[k]
arr[k] = _tmp
print("\t left={0}, arr[left] = {1}, k={2}, arr[k]={3}".format(left, arr[left], k, arr[k]))
print("\t result: {0}".format(arr))
# call quick_sort() recursively
if (left < k - 1):
quick_sort(arr, left, k - 1)
if (k + 1 < right):
quick_sort(arr, k + 1, right)
quick_sort(arr, left, right)
以下に実行結果の一例です。
inital array: [7, 4, 9, 2, 5, 6, 1, 3, 8] start: left=0, right=8, arr[left:right+1]=[7, 4, 9, 2, 5, 6, 1, 3, 8] _ref_value=7 i=2, arr[i]=9, k=7, arr[k]=3 left=0, arr[left] = 1, k=6, arr[k]=7 result: [1, 4, 3, 2, 5, 6, 7, 9, 8] start: left=0, right=5, arr[left:right+1]=[1, 4, 3, 2, 5, 6] _ref_value=1 result: [1, 4, 3, 2, 5, 6, 7, 9, 8] start: left=1, right=5, arr[left:right+1]=[4, 3, 2, 5, 6] _ref_value=4 left=1, arr[left] = 2, k=3, arr[k]=4 result: [1, 2, 3, 4, 5, 6, 7, 9, 8] start: left=1, right=2, arr[left:right+1]=[2, 3] _ref_value=2 result: [1, 2, 3, 4, 5, 6, 7, 9, 8] start: left=4, right=5, arr[left:right+1]=[5, 6] _ref_value=5 result: [1, 2, 3, 4, 5, 6, 7, 9, 8] start: left=7, right=8, arr[left:right+1]=[9, 8] _ref_value=9 left=7, arr[left] = 8, k=8, arr[k]=9 result: [1, 2, 3, 4, 5, 6, 7, 8, 9]
今後は、実際にpostgresqlでのクイックそーその実装部分に関して勉強して記事にしたいです。
アルゴリズムの基礎: 挿入ソート
アルゴリズムの基礎
勉強がてらに挿入ソートの復習とpythonでの実装をしてみたことのメモです。
単純挿入法(挿入ソート)
整列済みと未整列のデータがあって、未整列のデータを整列済みのデータ列に一つずつ挿入していく方法です。 ここでは、N個の数字を昇順にソートするアルゴリズムとして、挿入ソートを考えてみます。
なお、フローチャートは以下の本を参考に作成しました。

- 作者: 伊藤静香
- 出版社/メーカー: インプレス
- 発売日: 2012/05/14
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
今回のソートでは、リソースは限定しており、データを交換するためのtmp(1つのデータが入るだけ)と元のデータ配列でやりくりします。 そのため、値の入れ替え時にはバブルソートのように一つずつずれていくような動きをします。
ソート例
例として、以下のような5つの数字がランダムに並んでいる場合を考えます。 (tmpは挿入ソート時にデータの格納先として利用します)。 これを挿入ソートに従って、途中まで並べてみます。

1順目 - ソート対象の2つめの箱の値「2」をtmpに退避する - 1つめの箱の値「3」と2つめの箱の値「2」を比較 - 1つめの箱の値のほうが大きいため、値を入れ替える - 1つめの箱の値 → 2つめの箱の値, tmp(2つめの箱の値) → 1つめの箱の値 - 結果: 2 , 3, 5, 1, 4

2順目 - 2つめの箱の値「3」と3つめの箱の値「5」を比較 - 2つめの箱の値のほうが小さいため、既に昇順にソートされているので入れ替えは不要 - 結果: 2 , 3, 5, 1, 4

3順目 - 3つめの箱の値「5」と4つめの箱の値「1」を比較 - 3つめの箱の値のほうが大きいため、入れ替える - 3つめの箱の値 → 4つめの箱の値, tmp(4つめの箱の値) → 3つめの箱の値 - 結果: 2 , 3, 1, 5, 4

- 続けて、2つめの箱の値「3」と3つめの箱の値「1」を比較
- 2つめの箱の値のほうが大きいため、入れ替える
- 2つめの箱の値 → 3つめの箱の値, tmp(3つめの箱の値) → 2つめの箱の値
- 結果: 2 , 1, 3, 5, 4
- 2つめの箱の値のほうが大きいため、入れ替える

- さらに、1つめの箱の値「2」と2つめの箱の値「1」を比較
- 1つめの箱の値のほうが大きいため、入れ替える
- 1つめの箱の値 → 2つめの箱の値, tmp(2つめの箱の値) → 1つめの箱の値
- 結果: 1, 2 , 3, 5, 4
- 1つめの箱の値のほうが大きいため、入れ替える

4順目 - 4つめの箱の値「5」と5つめの箱の値「4」を比較 - 4つめの箱の値のほうが大きいため、入れ替える - 4つめの箱の値 → 5つめの箱の値, tmp(5つめの箱の値) → 4つめの箱の値 - 結果: 1, 2, 3, 4, 5

フローチャート
上記の実行例からも分かるように、2つのループを持ちます。 未整列のデータを1つ選ぶためのループと 選んだデータをどこに挿入するか値を比較するためのループです。

Pythonでの実装例
Pythonでの実装してみました。
import random
N = 5
# get random array
arr = list(range(1, N+1))
random.shuffle(arr)
print("inital array: {0}".format(arr))
_insert_value = None # a temporary variable for inserting the value
i = 1
k = None
while (i < N):
_insert_value = arr[i]
k = i
print("_insert_value = {0}".format(_insert_value))
while ( k > 0 and arr[k-1] > _insert_value):
arr[k] = arr[k-1]
k = k - 1
arr[k] = _insert_value
i = i + 1
print("i={0}, sorted:{1} , not sorted: : {2}".format(i, arr[:i], arr[i:]))
print("result: {0}".format(arr))
# 実行結果例 inital array: [3, 2, 5, 1, 4] _insert_value = 2 i=2, sorted:[2, 3] , not sorted: : [5, 1, 4] _insert_value = 5 i=3, sorted:[2, 3, 5] , not sorted: : [1, 4] _insert_value = 1 i=4, sorted:[1, 2, 3, 5] , not sorted: : [4] _insert_value = 4 i=5, sorted:[1, 2, 3, 4, 5] , not sorted: : [] result: [1, 2, 3, 4, 5]
estatからデータを取得してみる
estatのデータの取得と整理
matplotlibで利用するためのデータを取得するために、
外部のサイトからデータをAPIで取得して、そのデータをもとに図を書くということをしてみたいと思いました。
(今回の内容はデータを取得して、必要な形に整理するところまでです。matplotlibでのグラフ作成までは一度に整理できなかったのでまた今度です。)
既に、以下のサイトの記事で、estatのAPIを取得してから データを取り出すために試行錯誤するところについて 丁寧に記載されていますが、 今回は自分用のメモとして記事にしようと思います。
今回は利用するオープンデータとして、estatを使用しました。 ここから国勢調査などの国が提供しているデータを利用できます。
初めてやることなので、estatの一番上にあるデータである国勢調査 / 平成27年国勢調査 / 人口等基本集計(男女・年齢・配偶関係,世帯の構成,住居の状態など)を取得してみます。
ちなみに、APIで利用するURLは、estatのマイページから確認できます。
APIで取得できるデータ構造
データはjson形式で階層構造を以下のようになっています。 この中で、データとして活用する機会があるのは CLASS_OBJとVALUEです。
VALUEには目的のデータが含まれており、 CLASS_OBJにはデータとして使用する値の定義情報が 含まれています。
GET_STATS_DATA
|- PARAMETER
|
|- RESULT
|
|- STATISTICAL_DATA
|
|- CLASS_INF
| |
| |- CLASS_OBJ ☆ ここにあるデータを使う
|
|- DATA_INF
|
|- VALUE ☆ ここにあるデータを使う
APIからの取得は以下のように、上記サイトで指定されるURLを利用して、
urllib.request.urlopen(url)を使って取得します。
今回の場合は、urlにはestatが公開している「APIリクエストURL」を指定します。
また、取得したデータをファイルに保存したときに、 フォーマットが整った形でファイルに保存したい場合には、 json.dump()を使用します。
# coding: utf-8
import pandas as pd
import urllib.request
from io import StringIO
from IPython.core.display import display
import json
appid = "自分のIDを指定"
json_url = "https://api.e-stat.go.jp/rest/2.1/app/json/getStatsData?"
opt_url = "&lang=J&statsDataId=0003148500&metaGetFlg=Y&cntGetFlg=N§ionHeaderFlg=1"
url = json_url + "appId=" + appid + opt_url
print(url)
def get_json_data(url, file_name):
res_str = urllib.request.urlopen(url).read().decode('utf-8')
res = json.loads(res_str)
with open(file_name, mode="w", encoding='utf-8') as f:
json.dump(res, f, ensure_ascii=False, indent=4, sort_keys=True, separators=(',', ': '))
print("save data to {0}".format(file_name))
return pd.read_json(file_name, encoding='utf-8')
json_data = get_json_data(url, "tmp.json")
取得されるjsonのデータは以下のものです。
※ 一部省略しているデータ部分は「// 省略」と記載しています。
このjson形式のデータを利用するには、ここから「GET_STATS_DATA → STATISTICAL_DATA → DATA_INF → VALUE」のようにkeyを指定していって、値を取り出す必要があります。
{ "GET_STATS_DATA": { "PARAMETER": { // 今回は重要でないため省略 }, "RESULT": { "DATE": "2019-05-11T13:23:06.240+09:00", "ERROR_MSG": "正常に終了しました。", "STATUS": 0 }, "STATISTICAL_DATA": { "CLASS_INF": { "CLASS_OBJ": "[{'@id': 'tab', '@name': '表章項目..." // ...: データが多いため一部省略 }, "DATA_INF": { "NOTE": [ // 今回は重要でないため省略 ], "VALUE": "[{'@tab': '020', '@cat01': '00..." // ...: データが多いため一部省略 }, "RESULT_INF": { "FROM_NUMBER": 1, "TOTAL_NUMBER": 63530, "TO_NUMBER": 63530 }, "TABLE_INF": { // 今回は重要でないため省略 } } } }
STATISTICAL_DATA → DATA_INF → VALUE について
VALUEには、目的のデータが入れられています。 まずは、今回のAPIで得られたこれらのデータを確認していきます。
DATA_INFのVALUEには、データがlist ([...])として格納されています。 また、要素にはdict型{...}の形式で1つ1つデータが格納されています。
以下のものは2つの要素だけを取り出した結果です。
1つめの{...}の$には127,094,745の値が入っています。
(後でみるように日本の総人口の値を示していることが分かりますが)
[{'$': '127094745',
'@area': '00000',
'@cat01': '00710',
'@tab': '020',
'@time': '2015000000',
'@unit': '人'},
{'$': '116137232',
'@area': '00001',
'@cat01': '00710',
'@tab': '020',
'@time': '2015000000',
'@unit': '人'}]
この値が具体的に何を示しているかについては、 @area、@cat01、@tab、@timeを見て、判断する必要があります。
これら(@area、@cat01、@tab、@time)の定義については、次のCLASS_OBJに含まれています。
ちなみに、json形式の上記のデータをDataFrameにいれて、 head()で先頭5つを取り出すと以下のようになります。
| $ | @area | @cat01 | @tab | @time | @unit | |
|---|---|---|---|---|---|---|
| 0 | 127094745 | 00000 | 00710 | 020 | 2015000000 | 人 |
| 1 | 116137232 | 00001 | 00710 | 020 | 2015000000 | 人 |
| 2 | 10957513 | 00002 | 00710 | 020 | 2015000000 | 人 |
| 3 | 5381733 | 01000 | 00710 | 020 | 2015000000 | 人 |
| 4 | 4395172 | 01001 | 00710 | 020 | 2015000000 | 人 |
STATISTICAL_DATA → DATA_INF → VALUEのデータをDataFrameに入れるには、 json_dataからkeyを順に指定していき、取り出した値をDataFrameに渡します。
data_VALUE = json_data['GET_STATS_DATA']['STATISTICAL_DATA']['DATA_INF']['VALUE'] df_VALUE = pd.DataFrame(data_VALUE) display(df_VALUE.head())
STATISTICAL_DATA → CLASS_INF → CLASS_OBJ について
今度はCLASS_OBJについて詳しく見ていきます。
CLASS_OBJには、データに使用する値の情報が入っています。
具体的には国勢調査 / 平成27年国勢調査 / 人口等基本集計(男女・年齢・配偶関係,世帯の構成,住居の状態など)に記載されている「表章項目、全域・人口集中地区(2015)、地域(2015)、時間軸(年次)」のデータが入っています。
| @id | @name | CLASS | |
|---|---|---|---|
| 0 | tab | 表章項目 | [{'@code': '020', '@level': '', '@name': '人口',... |
| 1 | cat01 | 全域・人口集中地区(2015) | [{'@code': '00710', '@level': '1', '@name': '全... |
| 2 | area | 地域(2015) | [{'@code': '00000', '@level': '1', '@name': '全... |
| 3 | time | 時間軸(年次) | {'@code': '2015000000', '@level': '1', '@name'... |
さらに、この中の「地域(2015)」のデータをのぞいてみると、
以下のようにデータを持っているようです。
codeはprimary keyのようで、levelで都道府県、市町村などの単位を分けているようです。
何と都道府県、市町村などが一緒に含まれるテーブル構造になっています...
| @code | @level | @name | @parentCode | |
|---|---|---|---|---|
| 0 | 00000 | 1 | 全国 | NaN |
| 1 | 00001 | 1 | 全国市部 | NaN |
| 2 | 00002 | 1 | 全国郡部 | NaN |
| 3 | 01000 | 2 | 北海道 | 00000 |
| 4 | 01001 | 3 | 北海道市部 | 01000 |
| 5 | 01002 | 3 | 北海道郡部 | 01000 |
| 6 | 01100 | 4 | 札幌市 | 01000 |
| 7 | 01101 | 5 | 札幌市 中央区 | 01100 |
| 8 | 01102 | 5 | 札幌市 北区 | 01100 |
| 9 | 01103 | 5 | 札幌市 東区 | 01100 |
上記のデータを確認するには、以下のようにします。
STATISTICAL_DATA → CLASS_INF → CLASS_OBJのデータをDataFrameに入れるには、
json_dataからkeyを順に指定していき、取り出した値をDataFrameに渡します。
CLASS_OBJ内にある「@id==areaのCLASS」を取得するには、行と列の値を指定します。
今回は、列の取得をdf['列名']でしてから、行の取得をloc('行数')でしています。
data_CLASS_OBJ = json_data['GET_STATS_DATA']['STATISTICAL_DATA']['CLASS_INF']['CLASS_OBJ'] df_CLASS_OBJ = pd.DataFrame(data_CLASS_OBJ) display(df_CLASS_OBJ.head()) # @id==areaのCLASSの情報を確認 df_CLASS_OBJ_CLASS_area = pd.DataFrame(df_CLASS_OBJ['CLASS'].loc[2]) display(df_CLASS_OBJ_CLASS_area.head(n=10))
[補足] CLASS_OBJについて
ここでは、もう少しCLASS_OBJについてみておきます。
上でみたように、この中には@idの列でいうとtab, cat01, area, timeの4つが入っています。例えば、tabとareaは以下のようになっています。
tabではそれぞれの統計情報が一つにまとまっており、
areaではlevelに基づいて、都道府県のスケールや市町村のスケールで
の結果が混ざり合っています。
なので、実際にデータを取り扱う際には、不要なデータには
フィルターをかけて除外する必要があります。
[tab]について
| @code | @level | @name | @unit | |
|---|---|---|---|---|
| 0 | 020 | 人口 | 人 | |
| 1 | 106 | 組替人口(平成22年) | 人 | |
| 2 | 107 | 平成22年~27年の人口増減数 | 人 | |
| 3 | 108 | 平成22年~27年の人口増減率 | % | |
| 4 | 103 | 面積 | 平方km | |
| 5 | 104 | 人口密度 | NaN | |
| 6 | 109 | 世帯数 | 世帯 | |
| 7 | 110 | 組替世帯数(平成22年) | 世帯 | |
| 8 | 111 | 平成22年~27年の世帯数増減数 | 世帯 | |
| 9 | 112 | 平成22年~27年の世帯数増減率 |
[area]について
| @code | @level | @name | @parentCode | |
|---|---|---|---|---|
| 0 | 00000 | 1 | 全国 | NaN |
| 1 | 00001 | 1 | 全国市部 | NaN |
| 2 | 00002 | 1 | 全国郡部 | NaN |
| 3 | 01000 | 2 | 北海道 | 00000 |
| 4 | 01001 | 3 | 北海道市部 | 01000 |
| 5 | 01002 | 3 | 北海道郡部 | 01000 |
| 6 | 01100 | 4 | 札幌市 | 01000 |
| 7 | 01101 | 5 | 札幌市 中央区 | 01100 |
データのマージ
さて、DATA_INF内のVALUEに話は戻りますが、このままだと @area、@cat01、@tab、@timeの値がそれぞれID(数字)のままなので 具体的に何の値を示しているかわかりません。
そこで、ここではCLASS_OBJのデータとマージして具体的な値に置き換えていきます。
やることは、DataFrameのmerge()を用いて、それぞれをマージしていくことだけです。
(データの整理についてはあまり良い方法が見つからなかったので、drop()とrename()で強引に整えています。。。)。
これを実行すると、以下に意味のあるデータに変換できたものが取得できます。
なお、取得したデータは、df.to_csv()を使うことで、 csv形式のファイルとして保存できます
| $ | @area_level | @area | @cat01 | @tab | @time | |
|---|---|---|---|---|---|---|
| 0 | 127094745 | 1 | 全国 | 全域 | 人口 | 2015年 |
| 1 | 116137232 | 1 | 全国市部 | 全域 | 人口 | 2015年 |
| 2 | 10957513 | 1 | 全国郡部 | 全域 | 人口 | 2015年 |
| 3 | 5381733 | 2 | 北海道 | 全域 | 人口 | 2015年 |
| 4 | 4395172 | 3 | 北海道市部 | 全域 | 人口 | 2015年 |
以下の手順で上記のようにデータを整理できます。
# merge data
# もっと効率のよくて賢い方法があると思います。。。
def merge_data(df_VALUE, df_CLASS_OBJ):
df_CLASS_OBJ_CLASS_tab = pd.DataFrame(df_CLASS_OBJ['CLASS'].loc[0])
df_CLASS_OBJ_CLASS_cat01 = pd.DataFrame(df_CLASS_OBJ['CLASS'].loc[1])
df_CLASS_OBJ_CLASS_area = pd.DataFrame(df_CLASS_OBJ['CLASS'].loc[2])
df_CLASS_OBJ_CLASS_time = pd.DataFrame([df_CLASS_OBJ['CLASS'].loc[3]])
# time: DataFrame にはdict型のデータを持つリストを渡す必要がある
print("the original data is below")
display(df_VALUE.head())
df = df_VALUE.drop(columns=['@unit'])
# merge '@area'
df = pd.merge(df, df_CLASS_OBJ_CLASS_area, how='left',
left_on='@area', right_on='@code')
df = df.drop(columns=['@code', '@parentCode']) # @level is used for classification
df = df.drop(columns=['@area'])
df = df.rename(columns={'@name':'@area', '@level':'@area_level'})
# merge '@cat01'
df = pd.merge(df, df_CLASS_OBJ_CLASS_cat01, how='left',
left_on='@cat01', right_on='@code')
df = df.drop(columns=['@code', '@level'])
df = df.drop(columns=['@cat01'])
df = df.rename(columns={'@name':'@cat01'})
# merge '@tab'
df = pd.merge(df, df_CLASS_OBJ_CLASS_tab, how='left',
left_on='@tab', right_on='@code')
df = df.drop(columns=['@code', '@level', '@unit'])
df = df.drop(columns=['@tab'])
df = df.rename(columns={'@name':'@tab'})
# merge '@time'
df = pd.merge(df, df_CLASS_OBJ_CLASS_time, how='left',
left_on='@time', right_on='@code')
df = df.drop(columns=['@code', '@level'])
df = df.drop(columns=['@time'])
df = df.rename(columns={'@name':'@time'})
print("the merged data is below")
display(df.head())
return df
df = merge_data(df_VALUE, df_CLASS_OBJ)
# save data
df.to_csv("organized_data.csv")
整理したデータについて
整理して得られたデータについて、1つ確認してみます。 上記でマージしたデータを使って、都道府県ごとの人口データを取得します。 @area_levelを2(都道府県)、@cat01を全域、@tabを人口となっている行だけを取得します。
必要なデータを抽出すると、以下の表の形の結果が得られます。
| $ | @area_level | @area | @cat01 | @tab | @time | |
|---|---|---|---|---|---|---|
| 0 | 5381733 | 2 | 北海道 | 全域 | 人口 | 2015年 |
| 1 | 1308265 | 2 | 青森県 | 全域 | 人口 | 2015年 |
| 2 | 1279594 | 2 | 岩手県 | 全域 | 人口 | 2015年 |
| 3 | 2333899 | 2 | 宮城県 | 全域 | 人口 | 2015年 |
| 4 | 1023119 | 2 | 秋田県 | 全域 | 人口 | 2015年 |
| 5 | 1123891 | 2 | 山形県 | 全域 | 人口 | 2015年 |
| 6 | 1914039 | 2 | 福島県 | 全域 | 人口 | 2015年 |
| 7 | 2916976 | 2 | 茨城県 | 全域 | 人口 | 2015年 |
統計情報を確認してみると、次のことが読み取れるので、 きちんと目的のデータになっていることがわかります。
count数より、47行分のデータが存在すること
@areaのuniqueの値より、47行すべてが異なる@areaであること
@tabのuniqueの値より、すべての行が人口に関するデータであること
| $ | @area_level | @area | @cat01 | @tab | @time | |
|---|---|---|---|---|---|---|
| count | 47 | 47 | 47 | 47 | 47 | 47 |
| unique | 47 | 1 | 47 | 1 | 1 | 1 |
| top | 2304264 | 2 | 鹿児島県 | 全域 | 人口 | 2015年 |
| freq | 1 | 47 | 1 | 47 | 47 | 47 |
# (1) 都道府県ごとの人口データを取得
_tmp_df = df[ (df['@area_level'] == '2') \
& (df['@tab'] == '人口') \
& (df['@cat01'] == '全域')].reset_index(drop=True)
display(_tmp_df)
display(_tmp_df.describe())
次は、取得したデータをもとに、matplolibを用いてグラフを書いていこうと思います。