SPB Git

spb/wp44_uqo

Public
3.4 KB · 42 lines python
1#!/usr/bin/env python32"""WP44 — citation graph of the eligible corpus (Phase 3, structural layer).34Builds, in DuckDB and Parquet (data/processed/graph/):5  cit_edges_internal.parquet   (citing_id, cited_id, citing_year, cited_year)   both ends eligible6  cit_edges_external.parquet   (citing_id, cited_id, cited_field_id, cited_year, cited_type)  cited work outside the corpus,7                               resolved through the slim table of all 465 M OpenAlex works (field of the cited work)8  field_flows_yearly.csv       citing year × cited primary field (OpenAlex field) counts — interdisciplinary inflows (RQ4)9  cited_age_yearly.csv         distribution of citation age (citing year − cited year) by citing year10  reference_coverage_yearly.csv share of references resolvable (in OpenAlex), internal vs external11Category-level flows are produced by knowledge_graph/02_category_flows.py after classification."""12import argparse, os, duckdb131415def main():16    ap = argparse.ArgumentParser(); ap.add_argument("--root", required=True); a = ap.parse_args(); R = a.root17    G = os.path.join(R, "data/processed/graph"); out = os.path.join(R, "results/graph"); os.makedirs(G, exist_ok=True); os.makedirs(out, exist_ok=True)18    con = duckdb.connect(os.path.join(R, "data/processed/wp44.duckdb")); con.execute("SET threads TO 24; SET memory_limit='70GB';")19    con.execute("CREATE OR REPLACE TEMP TABLE E AS SELECT id, publication_year AS y, type, primary_field_id FROM corpus_works WHERE eligible")20    con.execute("""CREATE OR REPLACE TABLE cit_edges_internal AS21        SELECT r.work_id AS citing_id, r.ref_id AS cited_id, a.y AS citing_year, b.y AS cited_year22        FROM oa_references r JOIN E a ON a.id = r.work_id JOIN E b ON b.id = r.ref_id""")23    con.execute("""CREATE OR REPLACE TABLE cit_edges_external AS24        SELECT r.work_id AS citing_id, r.ref_id AS cited_id, a.y AS citing_year, s.publication_year AS cited_year, s.primary_field_id AS cited_field_id, s.type AS cited_type, s.cs_any_topic AS cited_cs_any25        FROM oa_references r JOIN E a ON a.id = r.work_id LEFT JOIN E b ON b.id = r.ref_id26        JOIN oa_slim s ON s.id = r.ref_id WHERE b.id IS NULL""")27    for t in ("cit_edges_internal", "cit_edges_external"):28        con.execute(f"COPY {t} TO '{G}/{t}.parquet' (FORMAT PARQUET, COMPRESSION ZSTD)")29    con.execute(f"""COPY (SELECT citing_year, 'internal' AS kind, NULL AS cited_field_id, count(*) n FROM cit_edges_internal GROUP BY 130                 UNION ALL SELECT citing_year, 'external', cited_field_id, count(*) FROM cit_edges_external GROUP BY 1,3 ORDER BY 1,2,3) TO '{out}/field_flows_yearly.csv' (HEADER)""")31    con.execute(f"""COPY (SELECT citing_year, citing_year - cited_year AS age, count(*) n FROM (SELECT citing_year, cited_year FROM cit_edges_internal UNION ALL SELECT citing_year, cited_year FROM cit_edges_external)32                 WHERE cited_year IS NOT NULL GROUP BY 1,2 ORDER BY 1,2) TO '{out}/cited_age_yearly.csv' (HEADER)""")33    con.execute(f"""COPY (SELECT e.y AS year, count(*) n_works, sum(n_refs) n_refs_declared,34                 (SELECT count(*) FROM cit_edges_internal i WHERE i.citing_year = e.y) n_internal,35                 (SELECT count(*) FROM cit_edges_external x WHERE x.citing_year = e.y) n_external36                 FROM E e JOIN corpus_works c ON c.id = e.id GROUP BY 1 ORDER BY 1) TO '{out}/reference_coverage_yearly.csv' (HEADER)""")37    print(open(f"{out}/reference_coverage_yearly.csv").read())383940if __name__ == "__main__":41    main()42
Files · 75471a74fc6ac4b5262d0a59571141fa1ebc1099
Menu

Theme