pycorrana.core.reporter 源代码

"""
结果导出与报告模块
==================
提供结果导出、文本摘要生成等功能。
"""

from typing import List, Dict, Optional
from datetime import datetime
import pandas as pd


[文档] class CorrReporter: """ 相关性报告生成器 提供结果导出和文本摘要功能。 """
[文档] def __init__(self): self.interpretation_guide = { (0.0, 0.1): ("极弱相关", "几乎无线性关联"), (0.1, 0.3): ("弱相关", "存在轻微线性关联"), (0.3, 0.5): ("中等相关", "存在中等程度线性关联"), (0.5, 0.7): ("强相关", "存在较强线性关联"), (0.7, 0.9): ("很强相关", "存在很强线性关联"), (0.9, 1.0): ("极强相关", "几乎完全线性相关"), }
[文档] def export_results(self, corr_matrix: pd.DataFrame, pvalue_matrix: pd.DataFrame, significant_pairs: List[dict], path: str, format: str = 'excel') -> str: """ 导出分析结果。 Parameters ---------- corr_matrix : pd.DataFrame 相关系数矩阵 pvalue_matrix : pd.DataFrame p值矩阵 significant_pairs : list 显著相关对列表 path : str 保存路径 format : str, default='excel' 格式:'excel'、'csv' Returns ------- str 保存的文件路径 """ if format.lower() in ['excel', 'xlsx', 'xls']: return self._export_excel( corr_matrix, pvalue_matrix, significant_pairs, path ) elif format.lower() == 'csv': return self._export_csv( corr_matrix, pvalue_matrix, significant_pairs, path ) else: raise ValueError(f"不支持的格式: {format}")
def _export_excel(self, corr_matrix: pd.DataFrame, pvalue_matrix: pd.DataFrame, significant_pairs: List[dict], path: str) -> str: """导出为Excel格式""" # 确保路径有正确后缀 if not path.endswith('.xlsx'): path += '.xlsx' with pd.ExcelWriter(path, engine='openpyxl') as writer: # 相关系数矩阵 corr_matrix.to_excel(writer, sheet_name='Correlation_Matrix') # p值矩阵 pvalue_matrix.to_excel(writer, sheet_name='PValue_Matrix') # 显著相关对 if significant_pairs: sig_df = pd.DataFrame(significant_pairs) sig_df = sig_df.sort_values('correlation', key=abs, ascending=False) sig_df.to_excel(writer, sheet_name='Significant_Pairs', index=False) # 摘要信息 summary_data = { 'Metric': [ '分析时间', '变量数量', '显著相关对数量', '强相关对数量 (|r| >= 0.7)', '中等相关对数量 (0.3 <= |r| < 0.7)', '弱相关对数量 (|r| < 0.3)', ], 'Value': [ datetime.now().strftime('%Y-%m-%d %H:%M:%S'), len(corr_matrix.columns), len(significant_pairs), len([p for p in significant_pairs if abs(p['correlation']) >= 0.7]), len([p for p in significant_pairs if 0.3 <= abs(p['correlation']) < 0.7]), len([p for p in significant_pairs if abs(p['correlation']) < 0.3]), ] } summary_df = pd.DataFrame(summary_data) summary_df.to_excel(writer, sheet_name='Summary', index=False) print(f" 结果已导出: {path}") return path def _export_csv(self, corr_matrix: pd.DataFrame, pvalue_matrix: pd.DataFrame, significant_pairs: List[dict], path: str) -> str: """导出为CSV格式(多个文件)""" import os base_path = path.replace('.csv', '') # 相关系数矩阵 corr_path = f"{base_path}_correlation.csv" corr_matrix.to_csv(corr_path) # p值矩阵 pval_path = f"{base_path}_pvalues.csv" pvalue_matrix.to_csv(pval_path) # 显著相关对 if significant_pairs: sig_path = f"{base_path}_significant.csv" sig_df = pd.DataFrame(significant_pairs) sig_df = sig_df.sort_values('correlation', key=abs, ascending=False) sig_df.to_csv(sig_path, index=False) print(f" 结果已导出到目录: {os.path.dirname(os.path.abspath(base_path))}") return base_path
[文档] def generate_summary(self, significant_pairs: List[dict], methods_used: Optional[Dict[str, str]] = None, max_pairs_display: int = 10) -> str: """ 生成文本摘要。 Parameters ---------- significant_pairs : list 显著相关对列表 methods_used : dict, optional 使用的方法记录 max_pairs_display : int, default=10 最多显示的变量对数量 Returns ------- str 摘要文本 """ lines = [] lines.append("=" * 60) lines.append("相关性分析摘要") lines.append("=" * 60) # 总体统计 lines.append(f"\n📊 总体统计:") lines.append(f" - 显著相关对总数: {len(significant_pairs)}") if significant_pairs: # 按强度分类 strong = [p for p in significant_pairs if abs(p['correlation']) >= 0.7] moderate = [p for p in significant_pairs if 0.3 <= abs(p['correlation']) < 0.7] weak = [p for p in significant_pairs if abs(p['correlation']) < 0.3] lines.append(f" - 强相关 (|r| >= 0.7): {len(strong)} 对") lines.append(f" - 中等相关 (0.3 <= |r| < 0.7): {len(moderate)} 对") lines.append(f" - 弱相关 (|r| < 0.3): {len(weak)} 对") # Top相关对 lines.append(f"\n🔝 Top {min(max_pairs_display, len(significant_pairs))} 显著相关对:") lines.append("-" * 60) for i, pair in enumerate(significant_pairs[:max_pairs_display], 1): var1, var2 = pair['var1'], pair['var2'] corr = pair['correlation'] pval = pair['p_value'] interp = pair['interpretation'] method = pair.get('method', 'unknown') direction = "正相关" if corr > 0 else "负相关" sig_marker = "***" if pval < 0.001 else "**" if pval < 0.01 else "*" if pval < 0.05 else "" lines.append(f"{i}. {var1} vs {var2}") lines.append(f" 相关系数: {corr:.4f} {sig_marker}") lines.append(f" p值: {pval:.4e}") lines.append(f" 方法: {method}") lines.append(f" 解释: {direction}, {interp}") lines.append("") # 方法统计 if methods_used: lines.append("\n📋 使用的方法统计:") method_counts = {} for method in methods_used.values(): method_counts[method] = method_counts.get(method, 0) + 1 for method, count in sorted(method_counts.items(), key=lambda x: -x[1]): lines.append(f" - {method}: {count} 次") # 解释指南 lines.append("\n📖 相关系数解释指南:") lines.append("-" * 60) lines.append(" |r| < 0.1: 极弱相关(几乎无线性关联)") lines.append(" 0.1 <= |r| < 0.3: 弱相关(轻微线性关联)") lines.append(" 0.3 <= |r| < 0.5: 中等相关(中等程度线性关联)") lines.append(" 0.5 <= |r| < 0.7: 强相关(较强线性关联)") lines.append(" 0.7 <= |r| < 0.9: 很强相关(很强线性关联)") lines.append(" |r| >= 0.9: 极强相关(几乎完全线性相关)") lines.append("") lines.append(" 显著性标记: *** p<0.001, ** p<0.01, * p<0.05") lines.append("\n" + "=" * 60) return "\n".join(lines)
[文档] def to_markdown(self, corr_matrix: pd.DataFrame, significant_pairs: List[dict], title: str = "相关性分析报告") -> str: """ 生成Markdown格式报告。 Parameters ---------- corr_matrix : pd.DataFrame 相关系数矩阵 significant_pairs : list 显著相关对列表 title : str, default='相关性分析报告' 报告标题 Returns ------- str Markdown格式文本 """ lines = [] lines.append(f"# {title}") lines.append("") lines.append(f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") lines.append("") # 概述 lines.append("## 概述") lines.append("") lines.append(f"- **变量数量**: {len(corr_matrix.columns)}") lines.append(f"- **显著相关对**: {len(significant_pairs)}") lines.append("") # 显著相关对表格 if significant_pairs: lines.append("## 显著相关对") lines.append("") lines.append("| 排名 | 变量1 | 变量2 | 相关系数 | p值 | 方法 | 解释 |") lines.append("|------|-------|-------|----------|-----|------|------|") for i, pair in enumerate(significant_pairs[:20], 1): var1 = pair['var1'] var2 = pair['var2'] corr = f"{pair['correlation']:.4f}" pval = f"{pair['p_value']:.2e}" method = pair.get('method', '-') interp = pair['interpretation'] lines.append(f"| {i} | {var1} | {var2} | {corr} | {pval} | {method} | {interp} |") lines.append("") # 相关系数矩阵 lines.append("## 相关系数矩阵") lines.append("") lines.append(corr_matrix.round(3).to_markdown()) lines.append("") # 解释指南 lines.append("## 解释指南") lines.append("") lines.append("| 相关系数范围 | 强度 | 说明 |") lines.append("|--------------|------|------|") lines.append("| |r| < 0.1 | 极弱 | 几乎无线性关联 |") lines.append("| 0.1 ≤ |r| < 0.3 | 弱 | 轻微线性关联 |") lines.append("| 0.3 ≤ |r| < 0.5 | 中等 | 中等程度线性关联 |") lines.append("| 0.5 ≤ |r| < 0.7 | 强 | 较强线性关联 |") lines.append("| 0.7 ≤ |r| < 0.9 | 很强 | 很强线性关联 |") lines.append("| |r| ≥ 0.9 | 极强 | 几乎完全线性相关 |") lines.append("") return "\n".join(lines)
[文档] def to_html(self, corr_matrix: pd.DataFrame, pvalue_matrix: pd.DataFrame, significant_pairs: List[dict], title: str = "相关性分析报告") -> str: """ 生成HTML格式报告。 Parameters ---------- corr_matrix : pd.DataFrame 相关系数矩阵 pvalue_matrix : pd.DataFrame p值矩阵 significant_pairs : list 显著相关对列表 title : str, default='相关性分析报告' 报告标题 Returns ------- str HTML格式文本 """ html = f""" <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{title}</title> <style> body {{ font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; background-color: #f5f5f5; }} h1 {{ color: #333; border-bottom: 2px solid #4CAF50; padding-bottom: 10px; }} h2 {{ color: #555; margin-top: 30px; }} table {{ border-collapse: collapse; width: 100%; background-color: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }} th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }} th {{ background-color: #4CAF50; color: white; }} tr:nth-child(even) {{ background-color: #f9f9f9; }} .positive {{ color: green; }} .negative {{ color: red; }} .summary {{ background-color: white; padding: 15px; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; }} .timestamp {{ color: #888; font-size: 0.9em; }} </style> </head> <body> <h1>{title}</h1> <p class="timestamp">生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p> <div class="summary"> <h2>概述</h2> <p><strong>变量数量:</strong> {len(corr_matrix.columns)}</p> <p><strong>显著相关对:</strong> {len(significant_pairs)}</p> </div> """ # 显著相关对表格 if significant_pairs: html += """ <h2>显著相关对</h2> <table> <tr> <th>排名</th> <th>变量1</th> <th>变量2</th> <th>相关系数</th> <th>p值</th> <th>方法</th> <th>解释</th> </tr> """ for i, pair in enumerate(significant_pairs[:20], 1): corr_class = 'positive' if pair['correlation'] > 0 else 'negative' html += f""" <tr> <td>{i}</td> <td>{pair['var1']}</td> <td>{pair['var2']}</td> <td class="{corr_class}">{pair['correlation']:.4f}</td> <td>{pair['p_value']:.2e}</td> <td>{pair.get('method', '-')}</td> <td>{pair['interpretation']}</td> </tr> """ html += " </table>" # 相关系数矩阵 html += """ <h2>相关系数矩阵</h2> <table> <tr> <th>变量</th> """ for col in corr_matrix.columns: html += f" <th>{col}</th>\n" html += " </tr>\n" for idx, row in corr_matrix.iterrows(): html += f" <tr>\n <td><strong>{idx}</strong></td>\n" for val in row: corr_class = 'positive' if val > 0 else 'negative' if val < 0 else '' html += f' <td class="{corr_class}">{val:.3f}</td>\n' html += " </tr>\n" html += """ </table> </body> </html> """ return html