55 lines
2.4 KiB
Python
55 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Rebuild data/sv_SE/first-name.tsv and last-name.tsv from SCB's whole-population name counts (CC0, "Källa: SCB").
|
|
|
|
data-import/names-se.py [--source URL_OR_FILE] [--first N] [--last N] [--cache DIR] [--out DIR]
|
|
|
|
A tilltalsnamn goes under each sex that carries it, so a name both sexes carry has two rows.
|
|
"""
|
|
import argparse
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import source
|
|
import xlsx
|
|
import tsv
|
|
|
|
SOURCE = "https://www.scb.se/contentassets/9fe7dbb460994c72b835163dbc491ef9/namn-med-minst-tva-barare-31-december-2022.xlsx"
|
|
OUT = Path(__file__).resolve().parent.parent / "data" / "sv_SE"
|
|
CACHE = Path(__file__).resolve().parent / "cache"
|
|
SHEETS = {"f": "Tilltalsnamn kvinnor", "m": "Tilltalsnamn män"}
|
|
SURNAMES = "Efternamn"
|
|
NAME = re.compile(r"^[^\W\d_]{2,}([ '-][^\W\d_]{2,})*$")
|
|
PARTICLES = {"af", "av", "da", "de", "del", "den", "der", "di", "dos", "du", "la", "le", "van", "von"}
|
|
|
|
|
|
def cased(name):
|
|
"""SCB's uppercase name as it is written: each part capitalised, a particle before another part lowercased."""
|
|
parts = name.lower().split(" ")
|
|
return " ".join(w if w in PARTICLES and len(parts) > 1 else w.title() for w in parts)
|
|
|
|
|
|
def counted(rows, top):
|
|
"""The top names of a sheet by bearers, initials and single letters dropped."""
|
|
names = [(cells[0], int(cells[1])) for cells in rows if len(cells) >= 2 and cells[1].isdigit() and NAME.match(cells[0])]
|
|
return sorted(names, key=lambda n: (-n[1], n[0]))[:top]
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
p.add_argument("--cache", default=str(CACHE))
|
|
p.add_argument("--first", type=int, default=2000, help="names per sex")
|
|
p.add_argument("--last", type=int, default=5000)
|
|
p.add_argument("--out", default=str(OUT))
|
|
p.add_argument("--source", default=SOURCE)
|
|
a = p.parse_args()
|
|
data = source.fetch(a.source, a.cache, "scb-namn-2022.xlsx", magic=b"PK")
|
|
first = [{"name": cased(n), "sex": sex, "count": c} for sex, sheet in SHEETS.items() for n, c in counted(xlsx.rows(data, sheet), a.first)]
|
|
last = [{"name": cased(n), "count": c} for n, c in counted(xlsx.rows(data, SURNAMES), a.last)]
|
|
out = Path(a.out)
|
|
tsv.write(out / "first-name.tsv", ["name", "sex", "count"], sorted(first, key=lambda r: (r["name"], r["sex"])))
|
|
tsv.write(out / "last-name.tsv", ["name", "count"], sorted(last, key=lambda r: r["name"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|