ensemble / app.py
ddooling's picture
added altair charts
dee01c8
import os
import json
import threading
import gradio as gr
import statistics
from scipy import stats
import numpy as np # Added import for numpy to compute percentiles
import altair as alt
import pandas as pd
DATA_DIR = './storage'
DATA_FILE = os.path.join(DATA_DIR, 'guesses.json')
lock = threading.Lock()
def ensure_data_directory():
os.makedirs(DATA_DIR, exist_ok=True)
def load_guesses():
ensure_data_directory()
if not os.path.exists(DATA_FILE):
with open(DATA_FILE, 'w') as f:
json.dump([], f)
with open(DATA_FILE, 'r') as f:
return json.load(f)
def save_guesses(guesses):
with open(DATA_FILE, 'w') as f:
json.dump(guesses, f)
def add_guess(guess):
with lock:
guesses = load_guesses()
guesses.append(guess)
save_guesses(guesses)
message = compute_statistics(guesses, include_message=True)
chart = generate_plot(guesses) # Generate the Altair chart
return message, None, chart # Return message, cleared input, and chart
def get_current_results():
with lock:
guesses = load_guesses()
message = compute_statistics(guesses, include_message=False)
chart = generate_plot(guesses)
return message, chart
def compute_statistics(guesses, include_message):
n = len(guesses)
if n == 0:
return "No guesses have been made yet."
average = sum(guesses) / n
median = statistics.median(guesses)
# Calculate IQR
Q1 = np.percentile(guesses, 25)
Q3 = np.percentile(guesses, 75)
IQR = Q3 - Q1
# Initialize the message
message = (
(f"Your guess has been recorded.\n" if include_message else "") +
f"Current average of all {n} guesses: {average:.2f}\n" +
f"Median of all guesses: {median:.2f}\n" +
f"Interquartile Range (IQR): {IQR:.2f}\n" +
"(The IQR is the range between the 25th percentile and 75th percentile of the data.)\n"
)
if n >= 2:
# Calculate sample standard deviation
s = statistics.stdev(guesses)
# Calculate standard error
SE = s / (n ** 0.5)
# Degrees of freedom
df = n - 1
# Confidence level (e.g., 95%)
confidence_level = 0.95
alpha = 1 - confidence_level
# Calculate critical t-value
t_value = stats.t.ppf(1 - alpha/2, df)
# Calculate margin of error
ME = t_value * SE
# Calculate confidence interval
ci_lower = average - ME
ci_upper = average + ME
# Append confidence interval to the message
message += f"95% confidence interval for the average: ({ci_lower:.2f}, {ci_upper:.2f})"
else:
# Not enough data to compute confidence interval
message += "Not enough data to compute confidence interval for the average."
return message
def generate_plot(guesses):
if len(guesses) < 2:
return None # Not enough data to plot
# Convert the list of guesses into a Pandas DataFrame
df = pd.DataFrame({'Guess': guesses})
# Histogram
histogram = alt.Chart(df).mark_bar().encode(
alt.X('Guess', bin=alt.Bin(maxbins=20), title='Guess Value'),
alt.Y('count()', title='Frequency'),
tooltip=[alt.Tooltip('count()', title='Frequency')]
).properties(
title='Histogram of Guesses',
width=500,
height=300
)
# CDF
df_sorted = df.sort_values('Guess').reset_index(drop=True)
df_sorted['ECDF'] = (df_sorted.index + 1) / len(df_sorted)
cdf = alt.Chart(df_sorted).mark_line(interpolate='step-after').encode(
x=alt.X('Guess', title='Guess Value'),
y=alt.Y('ECDF', title='Cumulative Probability'),
tooltip=[
alt.Tooltip('Guess', title='Guess Value'),
alt.Tooltip('ECDF', title='Cumulative Probability', format='.2f')
]
).properties(
title='Cumulative Distribution Function (CDF)',
width=500,
height=300
)
# Combine the two charts vertically
combined_chart = alt.vconcat(histogram, cdf).configure_title(
fontSize=16,
anchor='middle'
).interactive()
return combined_chart
with gr.Blocks() as demo:
gr.Markdown("# Collective Guessing Game")
gr.Markdown("Submit your guess and contribute to the global statistics!")
guess_input = gr.Number(label="Enter your guess")
submit_button = gr.Button("Submit Guess")
with gr.Accordion("View Current Results!", open=False):
output_text = gr.Textbox(label="Results", lines=10)
output_plot = gr.Plot(label="Data Visualization") # Plot component for Altair charts
refresh_button = gr.Button("Refresh Results")
submit_button.click(
fn=add_guess,
inputs=guess_input,
outputs=[output_text, guess_input, output_plot]
)
refresh_button.click(
fn=get_current_results,
outputs=[output_text, output_plot]
)
demo.load(fn=get_current_results, outputs=[output_text, output_plot])
demo.launch()