import pandas as pd | |
import matplotlib.pyplot as plt | |
import numpy as np | |
import cps | |
import seaborn as sns | |
sns.set_style('white') | |
plt.ion() | |
# This is a quick hack that gets the job done :/ | |
def repulsion(arr): | |
thresh = 2 # Max shift is 2 percentage points | |
for i in range(len(arr)-1): | |
diff = arr[i+1]-arr[i] | |
if diff < thresh: | |
arr[i] = arr[i+1]-thresh | |
if np.diff(arr).min() < thresh: | |
arr = repulsion(arr) | |
return arr | |
def percent_format(x): | |
return str(int(np.round(x))) + '%' | |
df = pd.read_csv('data.txt') | |
n = len(df) | |
vo = 0.0 # text vertical offset | |
hoa = 0.06 # horiztonal offset of agreement percent number | |
hoi = 0.26 # horizontal offset of issue text | |
# Apply repulsion, so that text doesn't overlap | |
df = df.sort_values('expert_agreement') | |
df['expert_plot_position'] = repulsion(df['expert_agreement'].copy().values) | |
df = df.sort_values('public_agreement') | |
df['public_plot_position'] = repulsion(df['public_agreement'].copy().values) | |
# Create columns with nicely formatted percents | |
df['expert_agreement_percent'] = df['expert_agreement'].apply(percent_format) | |
df['public_agreement_percent'] = df['public_agreement'].apply(percent_format) | |
plt.figure(figsize=[9,10]) | |
for i in range(n): | |
# Nicely formatted percents | |
plt.text(0 - hoa, df.ix[i, 'expert_plot_position'] + vo, df.ix[i, 'expert_agreement_percent'], ha='right', va='center', fontsize=8) | |
plt.text(1 + hoa, df.ix[i, 'public_plot_position'] + vo, df.ix[i, 'public_agreement_percent'], ha='left', va='center', fontsize=8) | |
# Policy question text | |
plt.text(0 - hoi, df.ix[i, 'expert_plot_position'] + vo, df.ix[i, 'issue'], ha='right', va='center', fontsize=8) | |
plt.text(1 + hoi, df.ix[i, 'public_plot_position'] + vo, df.ix[i, 'issue'], ha='left', va='center', fontsize=8) | |
# Gray lines | |
plt.plot([0, 1], [df.ix[i, 'expert_plot_position'], df.ix[i, 'public_plot_position']], linewidth=0.5, color=[0.5, 0.5, 0.5], zorder=1) | |
plt.scatter(np.zeros(n), df['expert_plot_position'].values, color=cps.blue, zorder=2) | |
plt.scatter(np.ones(n), df['public_plot_position'].values, color=cps.pink, zorder=2) | |
# Titles | |
plt.text(-0.3, 105, "Expert Agreement", ha='right', fontsize=16) | |
plt.text(1.3, 105, "Public Agreement", ha='left', fontsize=16) | |
# Clean up chart | |
sns.despine(bottom=True, left=True) # Remove axes | |
plt.gca().xaxis.set_major_locator(plt.NullLocator()) # Remove xticks | |
plt.gca().yaxis.set_major_locator(plt.NullLocator()) # Remove yticks | |
plt.gcf().set_tight_layout(True) | |
plt.xlim([-2.4, 3.4]) | |
plt.ylim([-2, 108]) | |
plt.savefig('fig_econ_poll.png', dpi=250) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment