Update app.py
Browse files
app.py
CHANGED
|
@@ -4,14 +4,13 @@ from scipy import stats
|
|
| 4 |
from typing import List, Dict, Any, Union, Tuple
|
| 5 |
import json
|
| 6 |
|
| 7 |
-
def
|
| 8 |
"""
|
| 9 |
-
Perform
|
| 10 |
|
| 11 |
Args:
|
| 12 |
group1 (str): Comma-separated values for group 1 (e.g., "1.2,2.3,3.4,2.1")
|
| 13 |
group2 (str): Comma-separated values for group 2 (e.g., "2.1,3.2,4.1,3.5")
|
| 14 |
-
equal_var (bool): If True, perform standard t-test assuming equal variances. If False, perform Welch's t-test
|
| 15 |
alternative (str): Alternative hypothesis - 'two-sided', 'less', or 'greater'
|
| 16 |
|
| 17 |
Returns:
|
|
@@ -25,24 +24,76 @@ def independent_t_test(group1: str, group2: str, equal_var: bool = True, alterna
|
|
| 25 |
if len(data1) < 2 or len(data2) < 2:
|
| 26 |
return {"error": "Each group must have at least 2 observations"}
|
| 27 |
|
| 28 |
-
# Perform t-test
|
| 29 |
-
t_stat, p_value = stats.ttest_ind(data1, data2, equal_var=
|
| 30 |
|
| 31 |
# Calculate descriptive statistics
|
| 32 |
desc1 = {"mean": np.mean(data1), "std": np.std(data1, ddof=1), "n": len(data1)}
|
| 33 |
desc2 = {"mean": np.mean(data2), "std": np.std(data2, ddof=1), "n": len(data2)}
|
| 34 |
|
| 35 |
-
# Degrees of freedom
|
| 36 |
-
|
| 37 |
-
df = len(data1) + len(data2) - 2
|
| 38 |
-
else:
|
| 39 |
-
# Welch's formula for unequal variances
|
| 40 |
-
s1_sq, s2_sq = desc1["std"]**2, desc2["std"]**2
|
| 41 |
-
n1, n2 = desc1["n"], desc2["n"]
|
| 42 |
-
df = (s1_sq/n1 + s2_sq/n2)**2 / ((s1_sq/n1)**2/(n1-1) + (s2_sq/n2)**2/(n2-1))
|
| 43 |
|
| 44 |
-
# Effect size (Cohen's d)
|
| 45 |
-
pooled_std = np.sqrt(((len(data1)-1)*desc1["std"]**2 + (len(data2)-1)*desc2["std"]**2) /
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
cohens_d = (desc1["mean"] - desc2["mean"]) / pooled_std
|
| 47 |
|
| 48 |
# Interpretation
|
|
@@ -50,7 +101,7 @@ def independent_t_test(group1: str, group2: str, equal_var: bool = True, alterna
|
|
| 50 |
effect_size_interp = "small" if abs(cohens_d) < 0.5 else "medium" if abs(cohens_d) < 0.8 else "large"
|
| 51 |
|
| 52 |
return {
|
| 53 |
-
"test_type":
|
| 54 |
"t_statistic": round(t_stat, 4),
|
| 55 |
"p_value": round(p_value, 6),
|
| 56 |
"degrees_of_freedom": round(df, 2),
|
|
@@ -59,10 +110,11 @@ def independent_t_test(group1: str, group2: str, equal_var: bool = True, alterna
|
|
| 59 |
"group2_stats": desc2,
|
| 60 |
"result": f"The difference between groups is {significance} (p = {p_value:.6f})",
|
| 61 |
"effect_size": f"Effect size (Cohen's d = {cohens_d:.4f}) is {effect_size_interp}",
|
| 62 |
-
"alternative_hypothesis": alternative
|
|
|
|
| 63 |
}
|
| 64 |
except Exception as e:
|
| 65 |
-
return {"error": f"Error performing t-test: {str(e)}"}
|
| 66 |
|
| 67 |
def paired_t_test(before: str, after: str, alternative: str = "two-sided") -> Dict[str, Any]:
|
| 68 |
"""
|
|
@@ -364,16 +416,26 @@ def correlation_test(x_values: str, y_values: str, method: str = "pearson") -> D
|
|
| 364 |
demo = gr.TabbedInterface(
|
| 365 |
[
|
| 366 |
gr.Interface(
|
| 367 |
-
fn=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
inputs=[
|
| 369 |
gr.Textbox(placeholder="1.2,2.3,3.4,2.1", label="Group 1 (comma-separated)"),
|
| 370 |
gr.Textbox(placeholder="2.1,3.2,4.1,3.5", label="Group 2 (comma-separated)"),
|
| 371 |
-
gr.Checkbox(value=True, label="Equal variances"),
|
| 372 |
gr.Dropdown(["two-sided", "less", "greater"], value="two-sided", label="Alternative hypothesis")
|
| 373 |
],
|
| 374 |
outputs=gr.JSON(),
|
| 375 |
-
title="
|
| 376 |
-
description="Compare means between two independent groups"
|
| 377 |
),
|
| 378 |
gr.Interface(
|
| 379 |
fn=paired_t_test,
|
|
@@ -432,9 +494,9 @@ demo = gr.TabbedInterface(
|
|
| 432 |
description="Test correlation between two variables"
|
| 433 |
)
|
| 434 |
],
|
| 435 |
-
tab_names=["
|
| 436 |
)
|
| 437 |
-
|
| 438 |
if __name__ == "__main__":
|
| 439 |
print(f"Gradio version: {gr.__version__}")
|
| 440 |
demo.launch(mcp_server=True)
|
|
|
|
| 4 |
from typing import List, Dict, Any, Union, Tuple
|
| 5 |
import json
|
| 6 |
|
| 7 |
+
def student_t_test(group1: str, group2: str, alternative: str = "two-sided") -> Dict[str, Any]:
|
| 8 |
"""
|
| 9 |
+
Perform Student's t-test (assumes equal variances) between two independent groups.
|
| 10 |
|
| 11 |
Args:
|
| 12 |
group1 (str): Comma-separated values for group 1 (e.g., "1.2,2.3,3.4,2.1")
|
| 13 |
group2 (str): Comma-separated values for group 2 (e.g., "2.1,3.2,4.1,3.5")
|
|
|
|
| 14 |
alternative (str): Alternative hypothesis - 'two-sided', 'less', or 'greater'
|
| 15 |
|
| 16 |
Returns:
|
|
|
|
| 24 |
if len(data1) < 2 or len(data2) < 2:
|
| 25 |
return {"error": "Each group must have at least 2 observations"}
|
| 26 |
|
| 27 |
+
# Perform Student's t-test (equal variances)
|
| 28 |
+
t_stat, p_value = stats.ttest_ind(data1, data2, equal_var=True, alternative=alternative)
|
| 29 |
|
| 30 |
# Calculate descriptive statistics
|
| 31 |
desc1 = {"mean": np.mean(data1), "std": np.std(data1, ddof=1), "n": len(data1)}
|
| 32 |
desc2 = {"mean": np.mean(data2), "std": np.std(data2, ddof=1), "n": len(data2)}
|
| 33 |
|
| 34 |
+
# Degrees of freedom (pooled)
|
| 35 |
+
df = len(data1) + len(data2) - 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
+
# Effect size (Cohen's d using pooled standard deviation)
|
| 38 |
+
pooled_std = np.sqrt(((len(data1)-1)*desc1["std"]**2 + (len(data2)-1)*desc2["std"]**2) / df)
|
| 39 |
+
cohens_d = (desc1["mean"] - desc2["mean"]) / pooled_std
|
| 40 |
+
|
| 41 |
+
# Interpretation
|
| 42 |
+
significance = "significant" if p_value < 0.05 else "not significant"
|
| 43 |
+
effect_size_interp = "small" if abs(cohens_d) < 0.5 else "medium" if abs(cohens_d) < 0.8 else "large"
|
| 44 |
+
|
| 45 |
+
return {
|
| 46 |
+
"test_type": "Student's t-test (equal variances assumed)",
|
| 47 |
+
"t_statistic": round(t_stat, 4),
|
| 48 |
+
"p_value": round(p_value, 6),
|
| 49 |
+
"degrees_of_freedom": df,
|
| 50 |
+
"cohens_d": round(cohens_d, 4),
|
| 51 |
+
"pooled_std": round(pooled_std, 4),
|
| 52 |
+
"group1_stats": desc1,
|
| 53 |
+
"group2_stats": desc2,
|
| 54 |
+
"result": f"The difference between groups is {significance} (p = {p_value:.6f})",
|
| 55 |
+
"effect_size": f"Effect size (Cohen's d = {cohens_d:.4f}) is {effect_size_interp}",
|
| 56 |
+
"alternative_hypothesis": alternative,
|
| 57 |
+
"assumption": "Assumes equal population variances"
|
| 58 |
+
}
|
| 59 |
+
except Exception as e:
|
| 60 |
+
return {"error": f"Error performing Student's t-test: {str(e)}"}
|
| 61 |
+
|
| 62 |
+
def welch_t_test(group1: str, group2: str, alternative: str = "two-sided") -> Dict[str, Any]:
|
| 63 |
+
"""
|
| 64 |
+
Perform Welch's t-test (does not assume equal variances) between two independent groups.
|
| 65 |
+
|
| 66 |
+
Args:
|
| 67 |
+
group1 (str): Comma-separated values for group 1 (e.g., "1.2,2.3,3.4,2.1")
|
| 68 |
+
group2 (str): Comma-separated values for group 2 (e.g., "2.1,3.2,4.1,3.5")
|
| 69 |
+
alternative (str): Alternative hypothesis - 'two-sided', 'less', or 'greater'
|
| 70 |
+
|
| 71 |
+
Returns:
|
| 72 |
+
dict: Test results including t-statistic, p-value, degrees of freedom, and interpretation
|
| 73 |
+
"""
|
| 74 |
+
try:
|
| 75 |
+
# Parse input data
|
| 76 |
+
data1 = [float(x.strip()) for x in group1.split(',') if x.strip()]
|
| 77 |
+
data2 = [float(x.strip()) for x in group2.split(',') if x.strip()]
|
| 78 |
+
|
| 79 |
+
if len(data1) < 2 or len(data2) < 2:
|
| 80 |
+
return {"error": "Each group must have at least 2 observations"}
|
| 81 |
+
|
| 82 |
+
# Perform Welch's t-test (unequal variances)
|
| 83 |
+
t_stat, p_value = stats.ttest_ind(data1, data2, equal_var=False, alternative=alternative)
|
| 84 |
+
|
| 85 |
+
# Calculate descriptive statistics
|
| 86 |
+
desc1 = {"mean": np.mean(data1), "std": np.std(data1, ddof=1), "n": len(data1)}
|
| 87 |
+
desc2 = {"mean": np.mean(data2), "std": np.std(data2, ddof=1), "n": len(data2)}
|
| 88 |
+
|
| 89 |
+
# Welch's degrees of freedom formula
|
| 90 |
+
s1_sq, s2_sq = desc1["std"]**2, desc2["std"]**2
|
| 91 |
+
n1, n2 = desc1["n"], desc2["n"]
|
| 92 |
+
df = (s1_sq/n1 + s2_sq/n2)**2 / ((s1_sq/n1)**2/(n1-1) + (s2_sq/n2)**2/(n2-1))
|
| 93 |
+
|
| 94 |
+
# Effect size (Cohen's d using separate standard deviations)
|
| 95 |
+
# For unequal variances, use the average of the two standard deviations
|
| 96 |
+
pooled_std = np.sqrt((desc1["std"]**2 + desc2["std"]**2) / 2)
|
| 97 |
cohens_d = (desc1["mean"] - desc2["mean"]) / pooled_std
|
| 98 |
|
| 99 |
# Interpretation
|
|
|
|
| 101 |
effect_size_interp = "small" if abs(cohens_d) < 0.5 else "medium" if abs(cohens_d) < 0.8 else "large"
|
| 102 |
|
| 103 |
return {
|
| 104 |
+
"test_type": "Welch's t-test (unequal variances)",
|
| 105 |
"t_statistic": round(t_stat, 4),
|
| 106 |
"p_value": round(p_value, 6),
|
| 107 |
"degrees_of_freedom": round(df, 2),
|
|
|
|
| 110 |
"group2_stats": desc2,
|
| 111 |
"result": f"The difference between groups is {significance} (p = {p_value:.6f})",
|
| 112 |
"effect_size": f"Effect size (Cohen's d = {cohens_d:.4f}) is {effect_size_interp}",
|
| 113 |
+
"alternative_hypothesis": alternative,
|
| 114 |
+
"assumption": "Does not assume equal population variances (recommended default)"
|
| 115 |
}
|
| 116 |
except Exception as e:
|
| 117 |
+
return {"error": f"Error performing Welch's t-test: {str(e)}"}
|
| 118 |
|
| 119 |
def paired_t_test(before: str, after: str, alternative: str = "two-sided") -> Dict[str, Any]:
|
| 120 |
"""
|
|
|
|
| 416 |
demo = gr.TabbedInterface(
|
| 417 |
[
|
| 418 |
gr.Interface(
|
| 419 |
+
fn=student_t_test,
|
| 420 |
+
inputs=[
|
| 421 |
+
gr.Textbox(placeholder="1.2,2.3,3.4,2.1", label="Group 1 (comma-separated)"),
|
| 422 |
+
gr.Textbox(placeholder="2.1,3.2,4.1,3.5", label="Group 2 (comma-separated)"),
|
| 423 |
+
gr.Dropdown(["two-sided", "less", "greater"], value="two-sided", label="Alternative hypothesis")
|
| 424 |
+
],
|
| 425 |
+
outputs=gr.JSON(),
|
| 426 |
+
title="Student's T-Test",
|
| 427 |
+
description="Compare means between two independent groups (assumes equal variances)"
|
| 428 |
+
),
|
| 429 |
+
gr.Interface(
|
| 430 |
+
fn=welch_t_test,
|
| 431 |
inputs=[
|
| 432 |
gr.Textbox(placeholder="1.2,2.3,3.4,2.1", label="Group 1 (comma-separated)"),
|
| 433 |
gr.Textbox(placeholder="2.1,3.2,4.1,3.5", label="Group 2 (comma-separated)"),
|
|
|
|
| 434 |
gr.Dropdown(["two-sided", "less", "greater"], value="two-sided", label="Alternative hypothesis")
|
| 435 |
],
|
| 436 |
outputs=gr.JSON(),
|
| 437 |
+
title="Welch's T-Test",
|
| 438 |
+
description="Compare means between two independent groups (does not assume equal variances - recommended)"
|
| 439 |
),
|
| 440 |
gr.Interface(
|
| 441 |
fn=paired_t_test,
|
|
|
|
| 494 |
description="Test correlation between two variables"
|
| 495 |
)
|
| 496 |
],
|
| 497 |
+
tab_names=["Student's T-Test", "Welch's T-Test", "Paired T-Test", "One-Sample T-Test", "ANOVA", "Chi-Square", "Correlation"]
|
| 498 |
)
|
| 499 |
+
|
| 500 |
if __name__ == "__main__":
|
| 501 |
print(f"Gradio version: {gr.__version__}")
|
| 502 |
demo.launch(mcp_server=True)
|