#!/usr/bin/env python3 """ build_noms_famille_gazetteer.py Construit deux gazetteers de noms de famille français à partir du fichier INSEE. Source : /home/dom/ai/anonymisation/data/insee/noms2008nat_txt.txt (TSV : NOM, puis effectifs par décennie 1891-2000) Sorties dans /home/dom/ai/anonymisation/data/insee/ : - noms_famille_france.txt : TOUS les noms (219K), un par ligne, majuscules - noms_famille_frequents.txt : noms avec total >= 100 ET longueur >= 3 caractères """ import os from collections import Counter INPUT_FILE = "/home/dom/ai/anonymisation/data/insee/noms2008nat_txt.txt" OUTPUT_DIR = "/home/dom/ai/anonymisation/data/insee" OUTPUT_ALL = os.path.join(OUTPUT_DIR, "noms_famille_france.txt") OUTPUT_FREQ = os.path.join(OUTPUT_DIR, "noms_famille_frequents.txt") MIN_TOTAL = 100 # seuil de fréquence pour le fichier "fréquents" MIN_LENGTH = 3 # longueur minimale pour le fichier "fréquents" SKIP_NAMES = {"AUTRES NOMS"} def main(): all_names = [] freq_names = [] frequencies = [] # pour les stats de distribution with open(INPUT_FILE, "r", encoding="utf-8") as f: header = f.readline() # skip header print(f"En-tête : {header.strip()}") for line in f: line = line.strip() if not line: continue parts = line.split("\t") nom = parts[0].strip() if nom in SKIP_NAMES: continue # Calculer la fréquence totale sur toutes les décennies total = 0 for val in parts[1:]: val = val.strip() try: total += int(val) except ValueError: pass # Tous les noms (uppercase, déjà le cas dans le fichier) nom_upper = nom.upper() all_names.append(nom_upper) frequencies.append(total) # Filtre pour les noms fréquents if total >= MIN_TOTAL and len(nom_upper) >= MIN_LENGTH: freq_names.append(nom_upper) # Écriture des fichiers with open(OUTPUT_ALL, "w", encoding="utf-8") as f: f.write("\n".join(all_names) + "\n") with open(OUTPUT_FREQ, "w", encoding="utf-8") as f: f.write("\n".join(freq_names) + "\n") # --- Stats --- print(f"\n{'='*60}") print(f"STATISTIQUES") print(f"{'='*60}") print(f"Fichier source : {INPUT_FILE}") print(f"Noms totaux lus : {len(all_names):>10,}") print(f" → {OUTPUT_ALL}") print(f"Noms fréquents : {len(freq_names):>10,} (total >= {MIN_TOTAL}, len >= {MIN_LENGTH})") print(f" → {OUTPUT_FREQ}") print(f"Noms exclus (filtre): {len(all_names) - len(freq_names):>10,}") # Distribution de fréquence print(f"\n--- Distribution des fréquences ---") buckets = [ (0, 0, "0 (hapax)"), (1, 9, "1-9"), (10, 49, "10-49"), (50, 99, "50-99"), (100, 499, "100-499"), (500, 999, "500-999"), (1000, 4999, "1 000-4 999"), (5000, 9999, "5 000-9 999"), (10000, 49999, "10 000-49 999"), (50000, 99999, "50 000-99 999"), (100000, float("inf"), "100 000+"), ] for lo, hi, label in buckets: count = sum(1 for freq in frequencies if lo <= freq <= hi) if count > 0: print(f" {label:>20s} : {count:>8,} noms") # Top 20 print(f"\n--- Top 20 noms les plus fréquents ---") indexed = list(zip(all_names, frequencies)) indexed.sort(key=lambda x: x[1], reverse=True) for i, (nom, freq) in enumerate(indexed[:20], 1): print(f" {i:>2}. {nom:<25s} {freq:>10,}") # Quelques stats globales total_naissances = sum(frequencies) print(f"\nTotal naissances couvertes : {total_naissances:>12,}") print(f"Fréquence médiane : {sorted(frequencies)[len(frequencies)//2]:>12,}") print(f"Fréquence moyenne : {total_naissances / len(frequencies):>12,.1f}") if __name__ == "__main__": main()