タイトル : 血圧降下剤の処方数量 データ追加
更新日 : 2024-03-20
カテゴリ : プログラミング
EXCELファイルを読み込んで、データ追加SQLを作成
ダウンロードしたEXCELファイルです
$ ls *性年齢別薬効分類別数量*
2014_性年齢別薬効分類別数量.xlsx 2018_性年齢別薬効分類別数量.xlsx
2015_性年齢別薬効分類別数量.xlsx 2019_性年齢別薬効分類別数量.xlsx
2016_性年齢別薬効分類別数量.xlsx 2020_性年齢別薬効分類別数量.xlsx
2017_性年齢別薬効分類別数量.xlsx 2021_性年齢別薬効分類別数量.xlsx
$
openpyxlでEXCELファイルを読み込んで、データベースのテーブルにデータを追加するSQLファイルを作成します。データ追加はINSERT文ではなくCOPY文で行います。その方が速いみたい
以下がそのPythonスクリプトです
import os
import argparse
import re
from openpyxl import load_workbook
parser = argparse.ArgumentParser(description='NDBオープンデータのEXCELを読み込んでSQLファイルを作成する')
parser.add_argument('book_file', help='EXCELファイル')
args = parser.parse_args()
# 年度を決める ファイル名は 2021_性年齢別薬効分類別数量.xlsx になっているとする
m = re.search("(\d+)_*", os.path.basename(args.book_file))
year = int(m.group(1))
# 出力SQLファイル
f_outs = {}
for key in ["category", "code", "quantity", "price"]:
f_outs[key] = open(f"insert_{key}_{year}.sql", "w")
# TRUNCATE文の出力
f_outs["category"].write("truncate public.iy_category cascade;\n")
f_outs["code"].write("truncate public.iy_code cascade;\n")
# f_outs["quantity"].write("truncate public.iy_quantity;\n")
# f_outs["price"].write("truncate public.iy_price;\n")
# COPY文の出力
f_outs["category"].write(
"COPY public.iy_category (id, name) FROM stdin;\n")
f_outs["code"].write(
"COPY public.iy_code (id, iy_category_id, name) FROM stdin;\n")
# idはautoincrementで指定なし
f_outs["quantity"].write(
"COPY public.iy_quantity (iy_code_id,year,quantity) FROM stdin;\n")
f_outs["price"].write(
"COPY public.iy_price (iy_code_id,year,price,generic) FROM stdin;\n")
# ワークブックの読み込み
wb = load_workbook(args.book_file)
# ワークシートを取得
sheet_names = [sheet_name for sheet_name in wb]
# 最初のシートを使う
sheet = sheet_names[0]
# 薬効分類
iy_cat_code_col_name = "薬効\n分類"
iy_code_col_name = "医薬品\nコード"
col_names = {
"name":"医薬品名",
"code": "医薬品\nコード",
"price": "薬価",
"generic" : "後発品\n区分",
"quantity" : "総計"
}
col_pos = dict()
# 薬効分類のコードパターン
iy_cat_code_pattern = re.compile(r'^\d{3}$')
iy_code_active = False
iy_category = -1
# 行のループ
for i_r, row in enumerate(sheet.iter_rows()):
# A列
col_a = str(row[0].value)
# 薬効分類の処理
if col_a and iy_cat_code_pattern.fullmatch(col_a):
col_b = str(row[1].value)
iy_category = int(col_a)
f_outs["category"].write(f"{int(col_a)}\t{col_b}\n")
if not iy_code_active:
iy_code_active = True
# 薬効分類の行
if col_a == iy_cat_code_col_name:
# 列の位置を求めておく
for i_c, col in enumerate(row):
for col_name in col_names:
if str(col.value) == col_names[col_name]:
col_pos[col_name] = i_c
# 医薬品コードの処理
if iy_code_active:
iy_name = str(row[col_pos["name"]].value)
iy_code = str(row[col_pos["code"]].value)
iy_price = str(row[col_pos["price"]].value)
iy_generic_str = str(row[col_pos["generic"]].value)
iy_quantity_str = str(row[col_pos["quantity"]].value)
if iy_generic_str == "1":
iy_generic = True
else:
iy_generic = False
if iy_quantity_str == "-":
iy_quantity = 0
else:
iy_quantity = int(float(iy_quantity_str))
f_outs["code"].write(
f"{iy_code}\t{iy_category}\t{iy_name}\n")
f_outs["quantity"].write(
f"{iy_code}\t{year}\t{iy_quantity}\n")
f_outs["price"].write(
f"{iy_code}\t{year}\t{iy_price}\t{iy_generic}\n")
# COPYの最後に \. を付加する
for key in f_outs:
f_outs[key].write("\\.\n")
一部分だけだけど、以下のSQLファイルを出力します
$ head -5 insert_price_2021.sql
COPY public.iy_price (iy_code_id,year,price,generic) FROM stdin;
620049101 2021 5.1 True
620049901 2021 5.7 True
611170508 2021 7 False
610443047 2021 30.9 False
$
SQLファイルを使ってデータを追加しました。 薬効分類 112個、医薬品が6736ですね。(今更だけど、薬の種類ってもっとあるかと思ってました...1万に届かないのですね...)
root@73dd79b8e94d:/insert-sql# psql -U bpress bpress
psql (16.1 (Debian 16.1-1.pgdg120+1))
Type "help" for help.
bpress=# select count(id) from iy_category;
count
-------
112
(1 row)
bpress=# select count(id) from iy_code;
count
-------
6736
(1 row)
bpress=# select count(id) from iy_price;
count
-------
36350
(1 row)
bpress=#