Wire local-only data setup workflow
This commit is contained in:
@@ -1,20 +1,16 @@
|
||||
#!/usr/bin/env julia
|
||||
#=
|
||||
02_enrich_output.jl - Enrich party positions CSV with metadata
|
||||
02_enrich_output.jl - Enrich party positions CSV with model-input-derived metadata
|
||||
|
||||
Fast post-processing script that adds party names, union membership status,
|
||||
and election results to the model output CSV. Operates purely on CSV files
|
||||
(no chain loading). Takes seconds, not minutes.
|
||||
Fast post-processing script that adds union membership status from the model-ready
|
||||
inputs. Operates purely on CSV files (no chain loading). Takes seconds, not minutes.
|
||||
|
||||
Usage:
|
||||
julia 02_enrich_output.jl # enriches latest party_positions_*.csv
|
||||
julia 02_enrich_output.jl somefile.csv # enriches a specific file
|
||||
|
||||
Adds columns:
|
||||
party_name_english - Full English party name (from data/party_names.csv)
|
||||
party_name_short - Standard abbreviation
|
||||
in_union - 1 if party's union had a joint manifesto that year, 0 otherwise
|
||||
pervote - Vote share (%) at election years; missing for non-election years
|
||||
=#
|
||||
|
||||
using CSV
|
||||
@@ -40,32 +36,7 @@ function enrich(input_file::String)
|
||||
output = CSV.read(input_file, DataFrame)
|
||||
println(" Rows: $(nrow(output)), Columns: $(ncol(output))")
|
||||
|
||||
# --- Party names ---
|
||||
party_names_file = joinpath("data", "party_names.csv")
|
||||
if isfile(party_names_file)
|
||||
names_df = CSV.read(party_names_file, DataFrame)
|
||||
name_lookup = Dict{Int, Tuple{String, String}}()
|
||||
for row in eachrow(names_df)
|
||||
short = ismissing(row.party_name_short) ? "" : string(row.party_name_short)
|
||||
name_lookup[row.partyfacts_id] = (string(row.party_name_english), short)
|
||||
end
|
||||
output.party_name_english = [
|
||||
haskey(name_lookup, pid) ? name_lookup[pid][1] : ""
|
||||
for pid in output.party_id
|
||||
]
|
||||
output.party_name_short = [
|
||||
haskey(name_lookup, pid) ? name_lookup[pid][2] : ""
|
||||
for pid in output.party_id
|
||||
]
|
||||
n_named = count(x -> x != "", output.party_name_english)
|
||||
println(" Party names: $n_named / $(nrow(output)) rows matched")
|
||||
else
|
||||
output.party_name_english = fill("", nrow(output))
|
||||
output.party_name_short = fill("", nrow(output))
|
||||
println(" WARNING: data/party_names.csv not found")
|
||||
end
|
||||
|
||||
# --- Union mapping (for in_union + pervote fallback) ---
|
||||
# --- Union mapping (for in_union) ---
|
||||
union_mapping_file = joinpath("data", "union_mapping.csv")
|
||||
constituent_to_union = Dict{Int, Int}()
|
||||
if isfile(union_mapping_file)
|
||||
@@ -126,49 +97,6 @@ function enrich(input_file::String)
|
||||
println(" WARNING: Could not compute in_union (missing files)")
|
||||
end
|
||||
|
||||
# --- Election results (pervote) ---
|
||||
election_file = joinpath("data", "election_data.csv")
|
||||
output.pervote = Vector{Union{Float64, Missing}}(missing, nrow(output))
|
||||
|
||||
if isfile(election_file)
|
||||
election_df = CSV.read(election_file, DataFrame)
|
||||
|
||||
# Build lookup: (party_id, year) -> pervote
|
||||
election_lookup = Dict{Tuple{Int, Int}, Float64}()
|
||||
for row in eachrow(election_df)
|
||||
election_lookup[(row.party, row.year)] = row.pervote
|
||||
end
|
||||
|
||||
n_filled = 0
|
||||
for i in 1:nrow(output)
|
||||
pid = output.party_id[i]
|
||||
yr = output.year[i]
|
||||
|
||||
# Direct match (standalone party)
|
||||
if haskey(election_lookup, (pid, yr))
|
||||
output.pervote[i] = election_lookup[(pid, yr)]
|
||||
n_filled += 1
|
||||
elseif hasproperty(output, :union_party_id) && !ismissing(output.union_party_id[i])
|
||||
# Union constituent: look up by union PF ID
|
||||
uid = output.union_party_id[i]
|
||||
if haskey(election_lookup, (uid, yr))
|
||||
output.pervote[i] = election_lookup[(uid, yr)]
|
||||
n_filled += 1
|
||||
end
|
||||
elseif haskey(constituent_to_union, pid)
|
||||
# Fallback: use union mapping even if union_party_id column not populated
|
||||
uid = constituent_to_union[pid]
|
||||
if haskey(election_lookup, (uid, yr))
|
||||
output.pervote[i] = election_lookup[(uid, yr)]
|
||||
n_filled += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
println(" pervote: $n_filled / $(nrow(output)) rows filled")
|
||||
else
|
||||
println(" WARNING: election_data.csv not found")
|
||||
end
|
||||
|
||||
# --- Reorder columns ---
|
||||
estimate_cols = Symbol[]
|
||||
for base in ["economic_lr", "galtan", "pro_market", "pro_welfare", "cosmopolitan", "traditional"]
|
||||
@@ -185,8 +113,7 @@ function enrich(input_file::String)
|
||||
output.country = replace(output.country, "MO" => "MK")
|
||||
|
||||
col_order = vcat(
|
||||
[:party_id, :party_name_english, :party_name_short, :country, :year, :segment_num,
|
||||
:union_party_id, :in_union, :pervote],
|
||||
[:party_id, :country, :year, :segment_num, :union_party_id, :in_union],
|
||||
estimate_cols
|
||||
)
|
||||
col_order = filter(c -> hasproperty(output, c), col_order)
|
||||
|
||||
Reference in New Issue
Block a user