{"id":29011823,"url":"https://github.com/finite-sample/endorsement","last_synced_at":"2026-03-08T21:38:00.801Z","repository":{"id":299898015,"uuid":"1002613923","full_name":"finite-sample/endorsement","owner":"finite-sample","description":"Derive Proportion Supporting A Group From an Endorsement Experiment","archived":false,"fork":false,"pushed_at":"2025-06-15T21:41:58.000Z","size":216,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-19T19:04:12.923Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/finite-sample.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-15T20:49:47.000Z","updated_at":"2025-06-19T01:21:37.000Z","dependencies_parsed_at":"2025-06-18T22:02:20.191Z","dependency_job_id":"bac9cd3c-a989-4d43-a71a-f75f04d7ff16","html_url":"https://github.com/finite-sample/endorsement","commit_stats":null,"previous_names":["soodoku/endorsement","finite-sample/endorsement"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/finite-sample/endorsement","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fendorsement","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fendorsement/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fendorsement/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fendorsement/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/finite-sample","download_url":"https://codeload.github.com/finite-sample/endorsement/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fendorsement/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267668844,"owners_count":24124973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-25T18:01:17.503Z","updated_at":"2026-03-08T21:37:55.752Z","avatar_url":"https://github.com/finite-sample.png","language":"Python","funding_links":[],"categories":["Stata","Python"],"sub_categories":[],"readme":"## Inferring Support From Endorsement Experiments\n\n## Manuscript\n\n* [Manuscript (pdf and .tex)](ms/)\n\n## Overview\n\nEndorsement experiments measure how group endorsements affect policy support, but interpreting the results to infer actual support for the endorsing group is complex. This toolkit provides:\n\n- **Theoretical bounds** on supporter proportions under different assumptions\n- **Baseline support analysis** using constant terms from regressions\n- **Continuous effects modeling** for non-binary outcomes\n- **Policy selection guidance** for optimal experimental design\n- **Visualization tools** for publication-ready figures\n\n## Quick Start\n\n### Option 1: Quick Analysis Script\nFor immediate analysis of your results:\n\n```python\n# Modify these parameters in endorsement_quick_analysis.py\nYOUR_ATE = -0.011              # Your treatment effect\nYOUR_CONSTANT = 0.8            # Your baseline support (if available)\nYOUR_SAMPLE_SIZE = 1500        # Your sample size\nYOUR_GROUP_NAME = \"militant groups\"\nYOUR_POLICY_NAME = \"infrastructure policies\"\n\n# Run analysis\npython endorsement_quick_analysis.py\n```\n\n### Option 2: Interactive Analysis\nUse the main notebook for detailed exploration:\n\n```python\nfrom endorsement_analysis_notebook import EndorsementAnalyzer\n\n# Initialize with your experimental results\nanalyzer = EndorsementAnalyzer(ate=-0.011, constant_term=0.8)\n\n# Get baseline analysis (most important!)\nresults = analyzer.baseline_support_analysis()\nprint(f\"Proportion supporting group: {results['proportion_supporters']:.1%}\")\n\n# Compare with binary framework\nbinary_results = analyzer.binary_framework_bounds()\nprint(f\"Binary framework max: {binary_results['p_max']:.1%}\")\n```\n\n## File Structure\n\n```\n├── scripts/endorsement_analysis_notebook.py    # Main analysis classes and functions\n├── scripts/endorsement_utils.py                # Utility functions and calculations  \n├── scripts/endorsement_viz.py                  # Visualization tools\n├── scripts/endorsement_quick_analysis.py       # Quick analysis script\n└── README.md                          # This file\n```\n\n## Key Methods\n\n### 1. Binary Framework\n**When to use:** Basic bounds without baseline information\n```python\np_max = (ate + 1) / 2\n```\n\n### 2. Baseline Support Analysis ⭐ **MOST IMPORTANT**\n**When to use:** When you have the constant term from your regression\n```python\nproportion_supporters = constant_term + ate\n```\n\n**Why it matters:** This can dramatically change interpretation. In Blair et al. (2013):\n- Binary framework: Max 49.5% supporters\n- Baseline analysis: **78.9% supporters** \n\n### 3. Continuous Effects\n**When to use:** Non-binary outcomes (e.g., 5-point scales)\n- Extreme scenario: `p_max = 1 + ate` (if opponents react maximally)\n- Symmetric effects: `p = ate/(2×effect_size) + 0.5`\n\n### 4. Policy Selection Scoring\n**When to use:** Designing new endorsement experiments\n```python\nscore = analyzer.policy_selection_score(\n    baseline_support=0.85,     # 80-90% optimal\n    ideological_score=0.9,     # Higher = more neutral\n    plausibility_score=0.8     # Higher = more believable\n)\n```\n\n## Real-World Example: Blair et al. (2013)\n\n**Study:** Pakistani attitudes toward militant groups via policy endorsements\n**Results:** ATE = -0.011, Baseline = 0.8\n\n**Traditional interpretation:** \"Negative sentiment toward militant groups\"\n**Our analysis:** \"78.9% actually support militant groups despite negative ATE\"\n\n```python\n# Replicate Blair et al. analysis\nresults = blair_replication()\n\n# Key insight: Small negative ATE + high baseline = majority support\n# This happens when popular policies get endorsed by controversial groups\n```\n\n## Understanding the Results\n\n### When Baseline Info Changes Everything\n\n| Scenario | Without Baseline | With Baseline (α=0.8) | Interpretation |\n|----------|------------------|----------------------|----------------|\n| ATE = -0.01 | Max 49.5% support | **78.9% support** | Majority support despite negative ATE |\n| ATE = -0.05 | Max 47.5% support | **75% support** | Still majority support |\n| ATE = +0.01 | Max 50.5% support | **80.1% support** | Strong majority support |\n\n### Why This Happens\n- **High baseline support** (α = 0.8) means 80% support policy in control\n- **Small negative ATE** (β = -0.011) means treatment drops to 78.9%  \n- Under **binary switching**: treatment group average = proportion of supporters\n- **Result:** 78.9% are supporters who always support when their group endorses\n\n## Policy Selection Guidelines\n\n### ✅ Good Policies for Endorsement Experiments\n- **Infrastructure development** (baseline ~85%, neutral, plausible)\n- **Public health programs** (baseline ~88%, neutral, plausible)\n- **Education funding** (baseline ~82%, neutral, plausible)\n\n### ❌ Poor Policies\n- **Military spending** (ideologically polarized)\n- **Universal healthcare** (ideologically polarized)  \n- **Gun control** (low baseline, polarized)\n\n### Optimal Characteristics\n1. **Baseline support: 80-90%** (room for opponents to move)\n2. **Ideologically neutral** (public goods, not partisan issues)\n3. **Plausible endorsement** (group could realistically support it)\n4. **Avoid ceiling effects** (not \u003e95% support)\n\n## Advanced Usage\n\n### Simulation for Heterogeneous Effects\n```python\n# Simulate individual-level heterogeneity\nsim_results = analyzer.simulate_heterogeneous_effects(\n    effect_distribution='normal',\n    std=0.05\n)\nprint(f\"Positive shifters: {sim_results['proportion_positive']:.1%}\")\n```\n\n### Sensitivity Analysis\n```python\n# Test robustness across ATE range\nate_range = np.linspace(-0.05, 0.05, 50)\nsensitivity_df = sensitivity_analysis(ate_range, constant_term=0.8)\n```\n\n### Optimization (for continuous outcomes)\n```python\n# Find maximum positive shifters using Hungarian algorithm\ncontrol_responses = generate_realistic_responses(100)['control']\ntreatment_responses = generate_realistic_responses(100)['treatment'] \noptimal_result = hungarian_optimization(control_responses, treatment_responses)\n```\n\n## Visualization Examples\n\n```python\nfrom endorsement_viz import *\n\n# Comprehensive bounds comparison\nfig1 = plot_bounds_comparison(ate=-0.011, constant_term=0.8)\n\n# Blair et al. replication with all details\nfig2 = plot_blair_replication()\n\n# Policy selection guidance\nfig3 = plot_policy_selection_guide()\n\n# Sensitivity analysis\nfig4 = plot_sensitivity_analysis(np.linspace(-0.05, 0.05, 50), constant_term=0.8)\n```\n\n## Dependencies\n\n```bash\npip install numpy pandas matplotlib seaborn scipy\n```\n\n## Citation\n\nIf you use this toolkit, please cite:\n\n```\nSood, Gaurav. (2025). Inferring Support from Endorsement Experiments.\n```\n\n## Key Takeaways\n\n1. **Baseline support information is crucial** - it can completely change your interpretation\n2. **Small negative ATEs don't necessarily mean opposition** when baseline support is high\n3. **Policy selection matters** - choose policies with 80-90% baseline support and ideological neutrality\n4. **Binary switching models provide clean theoretical foundations** before extending to continuous outcomes\n5. **External validation is important** - compare your estimates with other measures of support\n\n## Common Mistakes to Avoid\n\n❌ **Interpreting ATE alone** without considering baseline support\n❌ **Using polarized policies** that confound group and ideological effects  \n❌ **Assuming symmetric effects** without theoretical justification\n❌ **Ignoring sample size** in power calculations\n❌ **Focusing only on statistical significance** rather than substantive interpretation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinite-sample%2Fendorsement","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinite-sample%2Fendorsement","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinite-sample%2Fendorsement/lists"}