-
Notifications
You must be signed in to change notification settings - Fork 0
clean up tests and validate functions #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Compare wayne's polynomial output with R's poly(disp, 4) output | ||
| """ | ||
|
|
||
| import wayne | ||
| import polars as pl | ||
| import numpy as np | ||
|
|
||
| # Load the data | ||
| mtcars = pl.read_csv("data/mtcars.csv") | ||
| r_poly = pl.read_csv("data/mtcars_poly_4.csv") | ||
|
|
||
| print("Comparing wayne vs R poly(disp, 4) output...") | ||
| print("=" * 60) | ||
|
|
||
| # Test wayne's polynomial generation | ||
| formula = "mpg ~ wt + hp + cyl + wt*hp + poly(disp, 4) - 1" | ||
| wayne_result = wayne.trade_formula_for_matrix(mtcars, formula) | ||
|
|
||
| print(f"Wayne formula: {formula}") | ||
| print(f"Wayne result shape: {wayne_result.shape}") | ||
| print(f"Wayne columns: {wayne_result.columns}") | ||
|
|
||
| # Extract polynomial columns from wayne | ||
| wayne_poly_cols = [col for col in wayne_result.columns if col.startswith('disp_poly_')] | ||
| print(f"Wayne polynomial columns: {wayne_poly_cols}") | ||
|
|
||
| # Extract polynomial columns from R | ||
| r_poly_cols = [col for col in r_poly.columns if col.startswith('poly_disp_')] | ||
| print(f"R polynomial columns: {r_poly_cols}") | ||
|
|
||
| print("\n" + "=" * 60) | ||
| print("COMPARISON:") | ||
|
|
||
| # Compare the polynomial values | ||
| for i, (wayne_col, r_col) in enumerate(zip(wayne_poly_cols, r_poly_cols)): | ||
| wayne_values = wayne_result[wayne_col].to_list() | ||
| r_values = r_poly[r_col].to_list() | ||
|
|
||
| print(f"\nPolynomial term {i+1}:") | ||
| print(f" Wayne column: {wayne_col}") | ||
| print(f" R column: {r_col}") | ||
|
|
||
| # Check if values are close (within tolerance) | ||
| wayne_array = np.array(wayne_values) | ||
| r_array = np.array(r_values) | ||
|
|
||
| # Calculate differences | ||
| diff = np.abs(wayne_array - r_array) | ||
| max_diff = np.max(diff) | ||
| mean_diff = np.mean(diff) | ||
|
|
||
| print(f" Max difference: {max_diff:.10f}") | ||
| print(f" Mean difference: {mean_diff:.10f}") | ||
|
|
||
| # Check if they're close enough (tolerance of 1e-10) | ||
| tolerance = 1e-10 | ||
| is_close = np.allclose(wayne_array, r_array, atol=tolerance) | ||
| print(f" Within tolerance ({tolerance}): {is_close}") | ||
|
|
||
| if not is_close: | ||
| print(f" ❌ MISMATCH DETECTED!") | ||
| print(f" First 5 Wayne values: {wayne_values[:5]}") | ||
| print(f" First 5 R values: {r_values[:5]}") | ||
| else: | ||
| print(f" ✅ MATCH!") | ||
|
|
||
| print("\n" + "=" * 60) | ||
| print("SUMMARY:") | ||
| print(f"Wayne polynomial columns: {len(wayne_poly_cols)}") | ||
| print(f"R polynomial columns: {len(r_poly_cols)}") | ||
| print(f"Columns match: {len(wayne_poly_cols) == len(r_poly_cols)}") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,17 +70,43 @@ def trade_formula_for_matrix(df: pl.DataFrame, formula: str) -> pl.DataFrame: | |
| degree = transformation.get("parameters", {}).get("degree", 2) | ||
| generated_columns = transformation.get("generates_columns", []) | ||
|
|
||
| # Generate polynomial terms | ||
| for i, col_name in enumerate(generated_columns): | ||
| if i == 0: | ||
| # First polynomial term (linear) | ||
| poly_expr = pl.col(var_name) | ||
| else: | ||
| # Higher order terms (quadratic, cubic, etc.) | ||
| poly_expr = pl.col(var_name) ** (i + 1) | ||
| # Generate orthogonal polynomial terms using R's exact three-term recurrence relation | ||
| # Get the original data for orthogonalization | ||
| x_data = df[var_name].to_numpy() | ||
| import numpy as np | ||
|
|
||
| n = len(x_data) | ||
| P = np.zeros((n, degree + 1)) | ||
|
|
||
| # Initialize: P_0 = 1 (constant term) | ||
| P[:, 0] = 1.0 | ||
|
|
||
| # First polynomial: P_1 = x - mean(x) | ||
| if degree > 0: | ||
| P[:, 1] = x_data - np.mean(x_data) | ||
|
|
||
| # Three-term recurrence relation for higher order polynomials | ||
| for k in range(1, degree): | ||
| # Compute alpha_k = sum(x * P_k^2) / sum(P_k^2) | ||
| alpha_k = np.dot(x_data, P[:, k]**2) / np.dot(P[:, k], P[:, k]) | ||
|
|
||
| # Compute beta_k = sum(P_k^2) / sum(P_{k-1}^2) | ||
| beta_k = np.dot(P[:, k], P[:, k]) / np.dot(P[:, k-1], P[:, k-1]) | ||
|
|
||
| # Three-term recurrence: P_{k+1} = (x - alpha_k) * P_k - beta_k * P_{k-1} | ||
| P[:, k + 1] = (x_data - alpha_k) * P[:, k] - beta_k * P[:, k - 1] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Orthogonal Polynomial Calculation ErrorsThe orthogonal polynomial calculation has a few issues. Division by zero can occur in |
||
|
|
||
| # Normalize each polynomial to have unit variance | ||
| for k in range(1, degree + 1): | ||
| norm = np.sqrt(np.dot(P[:, k], P[:, k])) | ||
| if norm > 0: | ||
| P[:, k] = P[:, k] / norm | ||
|
|
||
| # Add the orthogonal polynomial columns (skip the constant term) | ||
| for i, col_name in enumerate(generated_columns): | ||
| poly_values = P[:, i + 1] # Skip P[:, 0] which is the constant term | ||
| result_df = result_df.with_columns( | ||
| poly_expr.alias(col_name) | ||
| pl.Series(poly_values).alias(col_name) | ||
| ) | ||
|
|
||
| # Add intercept if needed (unless formula has "- 1") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Missing Data Files Cause Test Failures
The new polynomial comparison test and script rely on hardcoded paths to
data/mtcars_poly_4.csvanddata/mtcars.csv. These data files aren't included in the repository, so tests and the script will fail with aFileNotFoundErrorif they're missing.Additional Locations (1)
tests/test_polynomials.py#L126-L127