TBR Result Objects#
Comprehensive guide to understanding and working with TBR result objects.
Overview#
The TBR package uses immutable result objects (frozen dataclasses) to return analysis results. This design ensures:
Type Safety: Clear return types with IDE autocomplete support
Immutability: Results cannot be accidentally modified
Rich Functionality: Helper methods for common operations
Easy Export: Built-in JSON/CSV export capabilities
Result Object Types#
1. TBRSummaryResult#
Returned by: summarize(), fit_summarize(), final_summary
Description: Contains cumulative treatment effect statistics for the entire test period.
Attributes#
Attribute |
Type |
Description |
|---|---|---|
|
float |
Cumulative treatment effect |
|
float |
Lower bound of credible interval |
|
float |
Upper bound of credible interval |
|
float |
Standard error |
|
float |
Posterior probability (effect > threshold) |
|
float |
Half-width of credible interval (margin of error) |
|
float |
Credibility level used |
|
float |
Threshold used for probability |
|
float |
Regression intercept |
|
float |
Regression slope |
|
float |
Residual standard error |
|
float |
Variance of alpha |
|
float |
Variance of beta |
|
float |
Covariance of alpha and beta |
|
int |
Degrees of freedom for t-distribution |
Methods#
# Check if effect is significant (lower > 0)
is_significant = summary.is_significant() # Returns: bool
# Convert to dictionary
data_dict = summary.to_dict() # Returns: dict
# Convert to DataFrame (single row)
df = summary.to_dataframe() # Returns: pd.DataFrame
# Export to JSON
summary.to_json('results.json')
# Export to CSV
summary.to_csv('results.csv')
Example Usage#
summary = model.summarize()
# Basic information
print(f"Effect: {summary.estimate:.2f}")
print(f"CI: [{summary.lower:.2f}, {summary.upper:.2f}]")
print(f"P(effect > 0): {summary.prob:.3f}")
# Check significance
if summary.is_significant():
print("✓ Statistically significant effect detected")
else:
print("✗ Effect not statistically significant")
# Regression diagnostics
print(f"Model: y = {summary.alpha:.2f} + {summary.beta:.4f}x")
print(f"Residual SE: {summary.sigma:.2f}")
print(f"Degrees of freedom: {summary.degrees_freedom}")
# Export
summary.to_json('analysis_results.json')
2. TBRPredictionResult#
Returned by: predict(), fit_predict()
Description: Contains counterfactual predictions and uncertainty estimates.
Attributes#
Attribute |
Type |
Description |
|---|---|---|
|
pd.DataFrame |
Predictions with |
|
int |
Number of predictions |
|
dict |
Model parameters used |
|
np.ndarray |
Control values used |
Properties#
Property |
Type |
Description |
|---|---|---|
|
float |
Average prediction |
|
float |
Average prediction std deviation |
Methods#
# Convert to dictionary
data_dict = result.to_dict()
# Convert to DataFrame
df = result.to_dataframe()
# Export to JSON
result.to_json('predictions.json')
# Export to CSV
result.to_csv('predictions.csv')
Example Usage#
predictions = model.predict()
# Summary statistics
print(f"Number of predictions: {predictions.n_predictions}")
print(f"Mean prediction: {predictions.mean_pred:.2f}")
print(f"Mean uncertainty: {predictions.mean_uncertainty:.2f}")
# Access predictions DataFrame
preds_df = predictions.predictions
print("\nFirst 5 predictions:")
print(preds_df.head())
# Plot predictions with uncertainty
import matplotlib.pyplot as plt
plt.plot(preds_df.index, preds_df['pred'], label='Prediction')
plt.fill_between(preds_df.index,
preds_df['pred'] - preds_df['predsd'],
preds_df['pred'] + preds_df['predsd'],
alpha=0.3, label='±1 SD')
plt.legend()
# Export
predictions.to_csv('counterfactual_predictions.csv')
3. TBRSubintervalResult#
Returned by: analyze_subinterval()
Description: Contains treatment effect estimates for a specific time window within the test period.
Attributes#
Attribute |
Type |
Description |
|---|---|---|
|
float |
Subinterval treatment effect |
|
float |
Lower CI bound |
|
float |
Upper CI bound |
|
float |
Standard error |
|
float |
Credibility level used |
|
int |
Starting day (1-indexed) |
|
int |
Ending day (1-indexed) |
|
int |
Number of days in interval |
Methods#
# Check if interval contains zero
contains_zero = result.contains_zero() # Returns: bool
# Check if effect is positive (lower > 0)
is_positive = result.is_positive() # Returns: bool
# Check if effect is negative (upper < 0)
is_negative = result.is_negative() # Returns: bool
# Convert to dictionary
data_dict = result.to_dict()
# Export to JSON
result.to_json('subinterval.json')
# Export to CSV
result.to_csv('subinterval.csv')
Example Usage#
# Analyze first week
week1 = model.analyze_subinterval(start_day=1, end_day=7)
# Basic information
print(f"Week 1 (Days {week1.start_day}-{week1.end_day}):")
print(f" Effect: {week1.estimate:.2f}")
print(f" CI ({week1.ci_level*100:.0f}%): [{week1.lower:.2f}, {week1.upper:.2f}]")
print(f" SE: {week1.se:.2f}")
# Interpretation
if week1.is_positive():
print(" ✓ Positive effect detected")
elif week1.is_negative():
print(" ✓ Negative effect detected")
else:
print(" ✗ Effect not significant (interval contains zero)")
# Compare multiple intervals
week2 = model.analyze_subinterval(start_day=8, end_day=14)
if week2.estimate > week1.estimate:
improvement = ((week2.estimate - week1.estimate) / week1.estimate) * 100
print(f"\nWeek 2 shows {improvement:.1f}% stronger effect than Week 1")
# Export
week1.to_json('week1_analysis.json')
Common Patterns#
Pattern 1: Quick Summary Check#
summary = model.summarize()
if summary.is_significant() and summary.prob > 0.95:
print(f"Strong evidence of positive effect: {summary.estimate:.2f}")
elif summary.is_significant():
print(f"Moderate evidence of positive effect: {summary.estimate:.2f}")
else:
print("No significant effect detected")
Pattern 2: Comparing Subintervals#
# Analyze multiple periods
early = model.analyze_subinterval(1, 15)
late = model.analyze_subinterval(16, 30)
# Compare
periods = pd.DataFrame({
'Period': ['Early (1-15)', 'Late (16-30)'],
'Effect': [early.estimate, late.estimate],
'Lower': [early.lower, late.lower],
'Upper': [early.upper, late.upper],
'Significant': [early.is_positive(), late.is_positive()]
})
print(periods)
Pattern 3: Exporting All Results#
# Fit model
model.fit(...)
# Export everything
model.summarize().to_json('summary.json')
model.predict().to_csv('predictions.csv')
# Export subintervals
for week in range(1, 5):
start = (week - 1) * 7 + 1
end = week * 7
result = model.analyze_subinterval(start, end)
result.to_json(f'week_{week}.json')
Pattern 4: Result DataFrame Conversion#
# Convert all result types to DataFrames
summary_df = model.summarize().to_dataframe()
predictions_df = model.predict().to_dataframe()
# Subinterval to dict then DataFrame
week1_dict = model.analyze_subinterval(1, 7).to_dict()
week1_df = pd.DataFrame([week1_dict])
Pattern 5: Accessing Model Parameters#
summary = model.summarize()
# Regression equation
print(f"Model: test = {summary.alpha:.2f} + {summary.beta:.4f} × control")
# Parameter uncertainty
print(f"α variance: {summary.var_alpha:.4f}")
print(f"β variance: {summary.var_beta:.4f}")
print(f"Covariance: {summary.cov_alpha_beta:.4f}")
# Model quality
print(f"Residual SE: {summary.sigma:.2f}")
print(f"Degrees of freedom: {summary.degrees_freedom}")
Result Object Comparison#
Feature |
TBRSummaryResult |
TBRPredictionResult |
TBRSubintervalResult |
|---|---|---|---|
Scope |
Full test period |
Test period predictions |
Custom time window |
Primary Use |
Overall effect |
Counterfactuals |
Temporal analysis |
Key Attribute |
|
|
|
Statistical Info |
Comprehensive |
Limited |
Moderate |
Helper Methods |
|
|
|
Export Options |
JSON, CSV |
JSON, CSV |
JSON, CSV |
Tips and Best Practices#
1. Result Immutability#
Result objects are frozen (immutable). This is intentional and prevents accidental modification:
summary = model.summarize()
# This will raise an error:
# summary.estimate = 100 # FrozenInstanceError
# Instead, create a new analysis:
model.set_params(level=0.95).fit(...)
new_summary = model.summarize()
2. Type Hints and IDE Support#
All result objects have complete type hints for excellent IDE support:
from tbr import TBRAnalysis
from tbr.core.results import TBRSummaryResult
def analyze_data(model: TBRAnalysis) -> TBRSummaryResult:
return model.fit(...).summarize()
# IDE will autocomplete all attributes and methods
3. Converting to Other Formats#
All result objects support conversion to common formats:
# To dictionary
data_dict = result.to_dict()
# To DataFrame (preserves structure)
df = result.to_dataframe()
# To JSON (with metadata)
result.to_json('output.json', include_metadata=True)
# To CSV (flattens structure)
result.to_csv('output.csv')
4. Accessing Raw Data#
For advanced use cases, access the underlying data:
# Summary: all attributes accessible
summary = model.summarize()
effect = summary.estimate
ci_lower = summary.lower
# Predictions: DataFrame is the main data
predictions = model.predict()
pred_values = predictions.predictions['pred'].values
control_used = predictions.control_values
# Subinterval: effect and bounds
interval = model.analyze_subinterval(1, 7)
interval_effect = interval.estimate
interval_days = interval.n_days
5. Combining Results#
Create comprehensive reports by combining multiple result types:
# Collect all results
results = {
'summary': model.summarize().to_dict(),
'predictions': model.predict().to_dict(),
'week1': model.analyze_subinterval(1, 7).to_dict(),
'week2': model.analyze_subinterval(8, 14).to_dict(),
}
# Export as single JSON
import json
with open('complete_analysis.json', 'w') as f:
json.dump(results, f, indent=2)
See Also#
API Reference - Complete API documentation
Quick Start - Getting started guide
Examples - Practical examples
Common Patterns - Best practices