-
Notifications
You must be signed in to change notification settings - Fork 1
/
plot.py
81 lines (71 loc) · 4.23 KB
/
plot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import matplotlib.pyplot as plt
import scipy.stats as stats
import scipy.optimize as opt
import numpy as np
from matplotlib import cm
from numpy.random import randn
from load_public_data import anes_opinion_data
from search_scotus_opinions_by_keywords import relevant_cases_scdb_df
from search_public_opinions_by_keywords import relevant_questions_anes_df
from polarity_scotus import sc_polarity
from polarity_public import po_polarity
CURRENT_YEAR = 2021
MIN_YEAR = 2000
NEUTRAL = 0 #the line deciding which side of the issue
SURVEY_YEAR_VCF_CODE = 'VCF0004' #ANES code for survey year
IMG_PATH='.\\plots\\' #path to save plot image
#create plot of both SCOTUS & public opinion polarity given {YEAR:POLARITY}
def scotus_v_public_plot(sc_polarity=None,po_polarity=None,title="ISSUE"):
#create figure, axes
fig = plt.figure()
ax = fig.add_subplot(111)
min_year = MIN_YEAR #minimum year for t-axis on plot
#PUBLIC OPINION
if po_polarity:
x_po=list(po_polarity.keys()) #get public opinion years
y_po=list(po_polarity.values()) #get public opinion polarity values
min_year = min(x_po+[min_year]) #update minimum year from public opinion data
slope, intercept, r_value, p_value, std_err = stats.linregress(x_po,y_po) #get basic stats
po_deg1=np.polyfit(x_po,y_po,1); f1 = np.poly1d(po_deg1) #degree 1 model for PO
p_shift_po=opt.fsolve(f1-NEUTRAL,2000) #find "paradigm shift" for PO. assuming one point of intersectionself. this is guaranteed for a linear fit.
ax.plot([p_shift_po], [NEUTRAL], marker='|', markersize=7, color="black") #include vertical lines at crossover moments
ax.scatter(x_po,y_po,c='b',marker="x",label='Public Opinion',vmin=-1, vmax=1) #average public opinion on issue
ax.plot(x_po,f1(x_po),'-b') #plot model for PO data
#SCOTUS OPINIONS
if sc_polarity:
x_sc=list(sc_polarity.keys()) #get scotus years
y_sc=list(sc_polarity.values()) #get scotus polarity values
min_year = min(x_sc+[min_year]) #update minimum year from scotus data
slope, intercept, r_value, p_value, std_err = stats.linregress(x_sc,y_sc) #get basic stats
sc_deg1=np.polyfit(x_sc,y_sc,1); g1 = np.poly1d(sc_deg1) #degree 1 model for SC
p_shift_sc=opt.fsolve(g1-NEUTRAL,2000) #find "paradigm shift" for SC assuming one point of intersection. this is guaranteed for a linear fit.
sc_scatter=ax.scatter(x_sc,y_sc,c='r',marker="+",label='Supreme Court',vmin=-1, vmax=1) #supreme court decisions
ax.plot(x_sc,g1(x_sc),'-r') #plot model for SC data
ax.plot([p_shift_sc], [NEUTRAL], marker='|', markersize=7, color="black") #include vertical lines at crossover moments
ax.axhline(y=NEUTRAL,color='k') #include horizontal neutral opinion line. purple='#551A8B'
ax.legend() #include legend
plt.xlabel('Time (year)') #label the x-axis, time in years
plt.ylabel('Polarity') #label the y-axis, liberal v. conservative polarity
plt.title('SCOTUS v. Public Opinion on ' + title) #include a title
plt.grid(True)
plt.yticks(np.arange(-1,2,1),["Conservative","Neutral","Liberal"]) #y-ticks are -1, 0, +1
plt.axis([min_year-2, CURRENT_YEAR, -1.1, 1.1])
#save the plot
plot_filename = "sc_v_po_" + title + ".png"
plt.savefig(IMG_PATH+plot_filename, bbox_inches='tight')
plt.gcf().clear()
return plot_filename
if __name__ == "__main__":
keywords=["equal"]
#get scotus polarity dict
rel_cases=relevant_cases_scdb_df(keywords) #relevant cases from SCDB as df
sc_polarity=sc_polarity(rel_cases) #scotus opinion polarity dict {year:polarity}
#get public polarity dict
rel_ques_df = relevant_questions_anes_df(keywords) #search the relevant q's & return ANES codebook sub-df
rel_vcf_codes = [SURVEY_YEAR_VCF_CODE]+list(rel_ques_df['vcf_code']) #get relevant ANES VCF codes. first code gives year
anes_df = anes_opinion_data() #load the full ANES response data
rel_ans_df = anes_df.filter(items=rel_vcf_codes) #filter the relevant repsonses/answers by VCF code
po_polarity=po_polarity(rel_ques_df,rel_ans_df) #dict {year:polarity} for public opinion
print(po_polarity)
#plot scotus opinions v. public opinions
scotus_v_public_plot(sc_polarity,po_polarity,title="+".join(keywords))