Thiloid commited on
Commit
038fb9b
·
verified ·
1 Parent(s): 2565b15

Upload 5 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tuda_logo.tif filter=lfs diff=lfs merge=lfs -text
37
+ Voto_Logo_bpg-03.png filter=lfs diff=lfs merge=lfs -text
Voto_Logo_bpg-03.png ADDED

Git LFS Details

  • SHA256: 1b87f6c85d47165bf9c9da16ec0d7bebd1736e5e7ee378bd118e1834b6547b3d
  • Pointer size: 131 Bytes
  • Size of remote file: 196 kB
Voto_purple.png ADDED
match_checker2000.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import json
3
+ import pandas as pd
4
+ import numpy as np
5
+ import matplotlib.pyplot as plt
6
+
7
+ footer="""<style>
8
+ a:link , a:visited{
9
+ color: blue;
10
+ background-color: transparent;
11
+ text-decoration: underline;
12
+ }
13
+
14
+ a:hover, a:active {
15
+ color: red;
16
+ background-color: transparent;
17
+ text-decoration: underline;
18
+ }
19
+
20
+ .footer {
21
+ position: fixed;
22
+ left: 0;
23
+ bottom: 0;
24
+ width: 100%;
25
+ background-color: cornflowerblue;
26
+ color: black;
27
+ text-align: center;
28
+ }
29
+ </style>
30
+ <div class="footer">
31
+ <p>This app was developed by <a href="https://www.voto.vote" target="_blank">VOTO</a>.
32
+ Developer: <a href="https://linkedin.com/in/thilo-dieing-bba5b2253" target="_blank">Thilo I. Dieing, M.Sc.</a></p>
33
+ </div>
34
+ """
35
+ st.markdown(footer,unsafe_allow_html=True)
36
+ def add_logo():
37
+ st.markdown(
38
+ """
39
+ <style>
40
+
41
+ [data-testid="stSidebarNav"]::before {
42
+ content: "Uni Mannheim ASR Team Project";
43
+ margin-left: 20px;
44
+ margin-top: 20px;
45
+ font-size: 20px;
46
+ position: relative;
47
+ top: 100px;
48
+ }
49
+ </style>
50
+ """,
51
+ unsafe_allow_html=True,
52
+ )
53
+ # functions
54
+
55
+
56
+
57
+ add_logo()
58
+ col1, col2 = st.columns(2)
59
+ with col1:
60
+ st.image("voto_purple.png", width=300)
61
+ with col2:
62
+ st.image("tuda_logo.tif", width=300)
63
+
64
+ # Title of the app
65
+ st.title("VOTO party insights")
66
+
67
+ # Allow the user to upload a file
68
+ uploaded_file = st.file_uploader("Upload the JSON file with your VOTO party answers", type=["json"])
69
+
70
+ # Check if a file is uploaded
71
+ if uploaded_file is not None:
72
+ try:
73
+ # Try to load the uploaded file as JSON
74
+ file_content = uploaded_file.read()
75
+ json_data = json.loads(file_content)
76
+
77
+ # If the file is valid JSON, show a success message
78
+
79
+ # Convert the JSON data to a DataFrame
80
+ if isinstance(json_data, list): # Expecting a list of dictionaries for a proper DataFrame
81
+ df = pd.DataFrame(json_data)
82
+ election=str(df["instance"].iloc[0])
83
+ statements = str(df["statement"].nunique())
84
+ statement_n = df["statement"].nunique()
85
+ parties = str(df["party_name"].nunique())
86
+ st.success("You have uploaded the party answers for the VOTO instance: "+election+" ("+statements+" statements; "+parties+" Parties)")
87
+
88
+ expander1 = st.expander("Statement Selection")
89
+ pivot_df = df.pivot(index='statement', columns='party_name', values='valuation')
90
+ # std
91
+ df['std_deviation'] = df.groupby('statement')['valuation'].transform('std')
92
+ # how many differnet postions
93
+ df['unique_postions'] = df.groupby('statement')['valuation'].transform('nunique')
94
+ # how many neutrals
95
+ df['n_neutral'] = df.groupby('statement')['valuation'].transform(lambda x: (x == 50).sum())
96
+ # standalone party postions
97
+ value_counts = df.groupby(['statement', 'valuation']).size().reset_index(name='Count')
98
+ unique_values = value_counts[value_counts['Count'] == 1]
99
+ single_counts = unique_values.groupby('statement').size().reset_index(name='SingleCount')
100
+
101
+ df = df.merge(single_counts, on='statement', how='left')
102
+ df['SingleCount'] = df['SingleCount'].fillna(0).astype(int)
103
+ #std without neutral
104
+ df_filtered = df[df['valuation'] != 50]
105
+ df_filtered['std_deviation2'] = df_filtered.groupby('statement')['valuation'].transform('std')
106
+ df2= df_filtered[["statement",'std_deviation2' ]].drop_duplicates()
107
+ df = df.merge(df2, on='statement', how='left', suffixes=('', '_new'))
108
+
109
+ sorted_single_counts = df[['statement', 'std_deviation']].drop_duplicates()
110
+ sorted_single_counts['AdjustedRank1'] = sorted_single_counts['std_deviation'].rank(method='dense', ascending=False).astype(int) - 1
111
+ df = df.merge(sorted_single_counts[['statement', 'AdjustedRank1']], on='statement', how='left', suffixes=('', '_new'))
112
+
113
+ sorted_single_counts = df[['statement', 'unique_postions']].drop_duplicates()
114
+ sorted_single_counts['AdjustedRank2'] = sorted_single_counts['unique_postions'].rank(method='dense', ascending=False).astype(int) - 1
115
+ df = df.merge(sorted_single_counts[['statement', 'AdjustedRank2']], on='statement', how='left', suffixes=('', '_new'))
116
+
117
+ sorted_single_counts = df[['statement', 'n_neutral']].drop_duplicates()
118
+ sorted_single_counts['AdjustedRank3'] = sorted_single_counts['n_neutral'].rank(method='dense').astype(int) - 1
119
+ df = df.merge(sorted_single_counts[['statement', 'AdjustedRank3']], on='statement', how='left', suffixes=('', '_new'))
120
+
121
+ sorted_single_counts = df[['statement', 'SingleCount']].drop_duplicates()
122
+ sorted_single_counts['AdjustedRank4'] = sorted_single_counts['SingleCount'].rank(method='dense', ascending=False).astype(int) - 1
123
+ df = df.merge(sorted_single_counts[['statement', 'AdjustedRank4']], on='statement', how='left', suffixes=('', '_new'))
124
+
125
+ sorted_single_counts = df[['statement', 'std_deviation2']].drop_duplicates()
126
+ sorted_single_counts['AdjustedRank5'] = sorted_single_counts['std_deviation2'].rank(method='dense', ascending=False).astype(int) - 1
127
+ df = df.merge(sorted_single_counts[['statement', 'AdjustedRank5']], on='statement', how='left', suffixes=('', '_new'))
128
+
129
+ df["statement_importance"]= (df["AdjustedRank1"]+df["AdjustedRank2"]+df["AdjustedRank3"]+df["AdjustedRank4"]+df["AdjustedRank5"])/5
130
+ df_pres= df[['statement',"statement_importance"]].drop_duplicates()
131
+ df_sorted1 = df_pres.sort_values(by='statement_importance')
132
+ df_sorted1.reset_index(drop=True, inplace=True)
133
+
134
+ df_sorted = df.sort_values(by='statement_importance')
135
+ df_sorted.reset_index(drop=True, inplace=True)
136
+ statn = expander1.slider("How many statements do you want in your final VOTO? You currently have **"+statements+ "** statements." , 0, int(statements),0)
137
+ if statn !=0:
138
+ expander1.write("**Based on that our metric recommends keeping the following " +str(statn) +" statements:**")
139
+ lstat=df_sorted1['statement'].tolist()
140
+ lstat1=lstat[:statn]
141
+ i=0
142
+ for l in lstat1:
143
+ i=i+1
144
+ expander1.markdown("<span style='color: green;'>"+str(i)+": "+l+"</span>", unsafe_allow_html=True)
145
+ expander1.write("**While the metric recommends dropping "+str(statement_n-statn) +" statements due to a lack of difference:**")
146
+ lstat=df_sorted1['statement'].tolist()
147
+ lstat1=lstat[statn:]
148
+ i=statn
149
+ for l in lstat1:
150
+ i=i+1
151
+ expander1.markdown("<span style='color: red;'>"+str(i)+": "+l+"</span>", unsafe_allow_html=True)
152
+ if expander1.button("Additional information on individual metric scores"):
153
+ expander1.dataframe(df_sorted)
154
+
155
+ expander2 = st.expander("Party Positions")
156
+ df = pd.DataFrame(json_data)
157
+ unique_party_names = df['party_name'].unique()
158
+ unique_party_names = [""] + list(unique_party_names) # Add an empty option
159
+ selected_party = expander2.selectbox("Select a Party", unique_party_names)
160
+ contains_25_or_75 = (25 in df['valuation'].values) or (75 in df['valuation'].values)
161
+ if contains_25_or_75:
162
+ y_ticks = [0, 25, 50, 75, 100] # Set y-ticks for scale 1 to 5
163
+ y_tick_labels = ['Strong Disagreement', 'Disagreement', 'Neutral', 'Agreement', 'Strong Agreement'] # Custom labels
164
+ else:
165
+ y_ticks = [0, 50, 100] # Set y-ticks for scale 1 to 3
166
+ y_tick_labels = ['Disagreement', 'Neutral', 'Agreement']
167
+ if selected_party: # Check if a party has been selected
168
+ df['short_text'] = df['statement'].apply(lambda x: ' '.join(x.split()[:11]))
169
+ filtered_df = df[df['party_name'] == selected_party]
170
+ fig, ax = plt.subplots()
171
+ ax.scatter(filtered_df['valuation'], filtered_df['short_text'], color='blue', s=100) # s is the size of points
172
+ ax.set_xlabel('Valuation')
173
+ ax.set_ylabel('Statements')
174
+ ax.set_title('Valuation by Statement')
175
+ ax.set_xticks(y_ticks) # Set y-ticks dynamically based on condition
176
+ ax.set_xticklabels(y_tick_labels)
177
+ plt.xticks(rotation=45)
178
+ ax.grid(True)
179
+ expander2.pyplot(fig)
180
+ expander3 = st.expander("Unique Party Positions")
181
+ df = pd.DataFrame(json_data)
182
+ unique_party_names = df['party_name'].unique()
183
+ unique_party_names = [""] + list(unique_party_names) # Add an empty option
184
+ selected_party = expander3.selectbox("Select a Party", unique_party_names, key="2")
185
+ contains_25_or_75 = (25 in df['valuation'].values) or (75 in df['valuation'].values)
186
+ if contains_25_or_75:
187
+ y_ticks = [0, 25, 50, 75, 100] # Set y-ticks for scale 1 to 5
188
+ y_tick_labels = ['Strong Disagreement', 'Disagreement', 'Neutral', 'Agreement', 'Strong Agreement'] # Custom labels
189
+ else:
190
+ y_ticks = [0, 50, 100] # Set y-ticks for scale 1 to 3
191
+ y_tick_labels = ['Disagreement', 'Neutral', 'Agreement']
192
+ if selected_party: # Check if a party has been selected
193
+ value_counts = df.groupby(['statement', 'valuation']).size().reset_index(name='Count')
194
+ unique_values = value_counts[value_counts['Count'] == 1]
195
+ unique_parties = df.merge(unique_values[['statement', 'valuation']], on=['statement', 'valuation'])
196
+ unique_parties_result = unique_parties[['statement', 'party_name', 'valuation']]
197
+ unique_parties_result['short_text'] = unique_parties_result['statement'].apply(lambda x: ' '.join(x.split()[:11]))
198
+ filtered_unique_parties_result = unique_parties_result[unique_parties_result['party_name'] == selected_party]
199
+ fig, ax = plt.subplots()
200
+ ax.scatter(filtered_unique_parties_result['valuation'], filtered_unique_parties_result['short_text'], color='blue', s=100) # s is the size of points
201
+ ax.set_xlabel('Valuation')
202
+ ax.set_ylabel('Statements')
203
+ ax.set_title('Valuation by Statement')
204
+ ax.set_xticks(y_ticks) # Set y-ticks dynamically based on condition
205
+ ax.set_xticklabels(y_tick_labels)
206
+ plt.xticks(rotation=45)
207
+ ax.grid(True)
208
+ expander3.pyplot(fig)
209
+
210
+
211
+
212
+ else:
213
+ st.warning("The JSON file structure is not suitable for DataFrame conversion. It should be a list of dictionaries.")
214
+
215
+ except json.JSONDecodeError:
216
+ # If the file is not a valid JSON, show an error message
217
+ st.error("This is not a valid JSON file. Please upload a valid JSON.")
218
+ else:
219
+ st.info("Please upload a JSON file to get started.")
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit
2
+ jsonlib-python3
3
+ pandas
4
+ numpy
5
+ matplotlib
tuda_logo.tif ADDED

Git LFS Details

  • SHA256: 27b1fdca81b707e9d36cc76950039f681c2884290d794c7aa231c4a4b1d297f3
  • Pointer size: 132 Bytes
  • Size of remote file: 2.81 MB