マイナンバーカード交付状況のExcelファイルをデータラングリング

csv変換時に小数点がおかしくなるので

float_format="%.1f"

で小数点一桁にするが、文字列扱いになるため

quoting=csv.QUOTE_MINIMAL

でダブルクォーテーションを外す

import csv
import datetime

import pandas as pd

def df_conv(df, col_name, col_1="人口", col_2="交付枚数"):

    df.set_axis(col_name, axis=1, inplace=True)

    population_date = df.iloc[-1][col_1].strftime("%Y/%m/%d")
    delivery_date = df.iloc[-1][col_2].strftime("%Y/%m/%d")

    df["人口算出基準日"] = population_date
    df["交付枚数算出基準日"] = delivery_date
    df.insert(0, "算出基準日", delivery_date)

    return df.iloc[:-1]

df0 = pd.read_excel(
    "https://www.soumu.go.jp/main_content/000703058.xlsx", sheet_name=1
).sort_index(ascending=False)

df0

dfg = df0.groupby((df0["Unnamed: 0"] == "時点").cumsum())

# 市区町村別

df1 = df_conv(
    dfg.get_group(1)
    .sort_index()
    .dropna(axis=1, how="all")
    .dropna(how="all")
    .iloc[2:]
    .reset_index(drop=True),
    ["都道府県名", "市区町村名", "総数(人口)", "交付枚数", "人口に対する交付枚数率"],
    "総数(人口)",
    "交付枚数",
)

df1["人口に対する交付枚数率"] = df1["人口に対する交付枚数率"].astype(float).round(3) * 100

df1["市区町村名"] = df1["市区町村名"].replace(r"\s", "", regex=True)
df1["市区町村名"] = df1["市区町村名"].mask(df1["都道府県名"] + df1["市区町村名"] == "兵庫県篠山市", "丹波篠山市")
df1["市区町村名"] = df1["市区町村名"].mask(df1["都道府県名"] + df1["市区町村名"] == "高知県高岡郡梼原町", "高岡郡檮原町")
df1["市区町村名"] = df1["市区町村名"].mask(df1["都道府県名"] + df1["市区町村名"] == "福岡県糟屋郡須惠町", "糟屋郡須恵町")

if pd.Timestamp(df1.iloc[0]["算出基準日"]) < datetime.date(2018, 10, 1):
    df1["市区町村名"] = df1["市区町村名"].mask(
        df1["都道府県名"] + df1["市区町村名"] == "福岡県那珂川市", "筑紫郡那珂川町"
    )
else:
    df1["市区町村名"] = df1["市区町村名"].mask(
        df1["都道府県名"] + df1["市区町村名"] == "福岡県筑紫郡那珂川町", "那珂川市"
    )

df_code = pd.read_csv(
    "https://docs.google.com/spreadsheets/d/e/2PACX-1vSseDxB5f3nS-YQ1NOkuFKZ7rTNfPLHqTKaSag-qaK25EWLcSL0klbFBZm1b6JDKGtHTk6iMUxsXpxt/pub?gid=0&single=true&output=csv",
    dtype={"団体コード": int, "都道府県名": str, "郡名": str, "市区町村名": str},
)

df_code["市区町村名"] = df_code["郡名"].fillna("") + df_code["市区町村名"]
df_code.drop("郡名", axis=1, inplace=True)

df1 = pd.merge(df1, df_code, on=["都道府県名", "市区町村名"], how="left")
df1["団体コード"] = df1["団体コード"].astype("Int64")

df1.to_csv(
    "all_localgovs.csv",
    index=False,
    quoting=csv.QUOTE_MINIMAL,
    float_format="%.1f",
    encoding="utf_8_sig",
)

df1

# 男女・年齢別

df2 = df_conv(
    dfg.get_group(2)
    .sort_index()
    .dropna(axis=1, how="all")
    .dropna(how="all")
    .iloc[3:]
    .reset_index(drop=True),
    [
        "年齢",
        "人口(男)",
        "人口(女)",
        "人口(計)",
        "交付件数(男)",
        "交付件数(女)",
        "交付件数(計)",
        "交付率(男)",
        "交付率(女)",
        "交付率(計)",
        "全体に対する交付件数割合(男)",
        "全体に対する交付件数割合(女)",
        "全体に対する交付件数割合(計)",
    ],
    "人口(男)",
    "交付件数(男)",
)

df2["交付率(男)"] = df2["交付率(男)"].astype(float).round(3) * 100
df2["交付率(女)"] = df2["交付率(女)"].astype(float).round(3) * 100
df2["交付率(計)"] = df2["交付率(計)"].astype(float).round(3) * 100
df2["全体に対する交付件数割合(男)"] = df2["全体に対する交付件数割合(男)"].astype(float).round(3) * 100
df2["全体に対する交付件数割合(女)"] = df2["全体に対する交付件数割合(女)"].astype(float).round(3) * 100
df2["全体に対する交付件数割合(計)"] = df2["全体に対する交付件数割合(計)"].astype(float).round(3) * 100

df2.to_csv(
    "demographics.csv",
    index=False,
    quoting=csv.QUOTE_MINIMAL,
    float_format="%.1f",
    encoding="utf_8_sig",
)

df2

# 都道府県一覧

df3 = df_conv(
    dfg.get_group(3)
    .sort_index()
    .dropna(axis=1, how="all")
    .dropna(how="all")
    .iloc[2:]
    .reset_index(drop=True),
    ["都道府県名", "総数(人口)", "交付枚数", "人口に対する交付枚数率"],
    "総数(人口)",
)

df3["人口に対する交付枚数率"] = df3["人口に対する交付枚数率"].astype(float).round(3) * 100

df3.to_csv(
    "all_prefectures.csv",
    index=False,
    quoting=csv.QUOTE_MINIMAL,
    float_format="%.1f",
    encoding="utf_8_sig",
)

df3

# 団体区分別

df4 = df_conv(
    dfg.get_group(6)
    .sort_index()
    .dropna(axis=1, how="all")
    .dropna(how="all")
    .iloc[2:]
    .reset_index(drop=True),
    ["区分", "人口", "交付枚数", "人口に対する交付枚数率"],
)

df4["人口に対する交付枚数率"] = df4["人口に対する交付枚数率"].astype(float).round(3) * 100

df4 = df4.round({"人口に対する交付枚数率": 1})

df4.to_csv(
    "summary_by_types.csv",
    index=False,
    quoting=csv.QUOTE_MINIMAL,
    float_format="%.1f",
    encoding="utf_8_sig",
)

df4