当前位置:首页>python>【重复测量纵向数据】Python10非线性混合效应模型(Nonlinear Mixed-Effects Models,NLME)

【重复测量纵向数据】Python10非线性混合效应模型(Nonlinear Mixed-Effects Models,NLME)

  • 2026-03-23 20:14:40
【重复测量纵向数据】Python10非线性混合效应模型(Nonlinear Mixed-Effects Models,NLME)
【重复测量纵向数据】
Python10.非线性混合效应模型(Nonlinear Mixed-Effects Models,NLME)

纵向数据是在不同时间点上对同一组个体、物体或实体进行重复观测所收集的数据。它就像给研究对象拍摄“动态影像”,能记录其随时间变化的过程,帮助我们理解趋势、模式和影响因素。

01
🔬 模型的概念、原理、思想

10.非线性混合效应模型

概念:当响应变量与时间或协变量之间的关系遵循非线性函数时(如S型增长、指数衰减),在混合模型框架内引入非线性函数的模型。

原理:模型形式为:`Y_ij=f(φ_i,X_ij)+ε_ij`。其中`f`是非线性函数,`φ_i`是包含固定和随机效应的个体参数向量。通过FOCE等算法迭代估计。

思想:“非线性关系的个体化”。承认许多生物、心理过程遵循固有的非线性规律,并将这种规律与个体随机变异相结合进行建模。

可视化:非线性拟合曲线图:绘制总体平均的非线性预测曲线,并可叠加显示基于个体参数的预测曲线。

公共卫生意义:药代动力学研究:描述药物在个体体内的血药浓度-时间曲线(常为指数衰减),并研究肝肾功能对曲线参数的影响。也用于描述疾病(如HIV感染后CD4细胞计数)的非线性变化轨迹。

02
💡 22种重复测量纵向数据分析模型

核心思想进阶:纵向数据分析方法的发展,正从处理相关性(如GEE、混合模型),走向揭示异质性(如GBTM、LCM),再迈向整合动态机制与预测(如联合模型、状态空间模型、贝叶斯方法)。

1.数据预处理:

2.模型拟合:

3.模型可视化:

4.结果保存与报告生成

03
💎模型实现代码介绍

总的来说,纵向数据因其时间延续性对象一致性,成为了解事物动态发展过程、探究因果关系的强大工具。

当然,处理纵向数据也伴随一些挑战,例如成本较高、可能存在数据缺失,且分析方法通常比处理横截面数据更为复杂。

下面我们使用R语言进行纵向数据Python10.非线性混合效应模型(Nonlinear Mixed-Effects Models,NLME)

# pip install pandas numpy matplotlib seaborn scipy statsmodels scikit-learn python-docximport osimport warningsimport numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsfrom scipy import statsfrom scipy.optimize import curve_fitimport statsmodels.api as smimport statsmodels.formula.api as smffrom statsmodels.tools.tools import add_constantfrom sklearn.preprocessing import StandardScalerfrom datetime import datetimeimport jsonfrom pathlib import Pathfrom docx import Documentfrom docx.shared import Inchesfrom docx.enum.text import WD_ALIGN_PARAGRAPHfrom docx.enum.table import WD_TABLE_ALIGNMENTimport matplotlibmatplotlib.use('Agg')  # 非交互式后端# 设置中文显示plt.rcParams['font.sans-serif'] = ['SimHei''DejaVu Sans']plt.rcParams['axes.unicode_minus'] = False# 忽略警告warnings.filterwarnings('ignore')# ==============================# 0. 设置工作目录和结果文件夹# ==============================# 自动寻找桌面路径desktop_path = Path.home() / 'Desktop'os.chdir(desktop_path)# 创建结果文件夹results_dir = desktop_path / '10-NLME结果'results_dir.mkdir(exist_ok=True)os.chdir(results_dir)# ==============================# 1. 数据读取与预处理# ==============================print("1. 数据读取与预处理...")# 读取Excel数据try:    data_file = desktop_path / 'longitudinal_data.xlsx'    simple_data = pd.read_excel(data_file, sheet_name='Simple_Dataset')except FileNotFoundError:print(f"错误: 未找到文件 {data_file}")print("创建示例数据以供演示...")# 创建示例数据    np.random.seed(123)    n_subjects = 100    n_timepoints = 5    subjects = []times = []    outcomes = []    treatments = []    ages = []    baselines = []    sexes = []    schools = []    dates = []    treatments_list = ['A''B''C''D']for i in range(n_subjects):        subject_id = f"SUB{i + 1:03d}"        treatment = np.random.choice(treatments_list)        age = np.random.normal(45, 10)        baseline = np.random.normal(50, 10)        sex = np.random.choice(['M''F'])        school = f"SCH{np.random.randint(1, 6)}"# 指数增长轨迹        time_points = np.arange(n_timepoints)        base_outcome = baseline * np.exp(0.05 * time_points)# 添加随机效应        random_effect = np.random.normal(0, 5)# 添加治疗效应if treatment == 'B':            treatment_effect = 5elif treatment == 'C':            treatment_effect = 10elif treatment == 'D':            treatment_effect = 15else:            treatment_effect = 0        outcome = base_outcome + random_effect + treatment_effect + np.random.normal(0, 2, n_timepoints)# 添加到列表        subjects.extend([subject_id] * n_timepoints)        times.extend(time_points)        outcomes.extend(outcome)        treatments.extend([treatment] * n_timepoints)        ages.extend([age] * n_timepoints)        baselines.extend([baseline] * n_timepoints)        sexes.extend([sex] * n_timepoints)        schools.extend([school] * n_timepoints)        dates.extend([datetime(2023, 1, 1) + pd.Timedelta(days=t * 30) for t in time_points])    simple_data = pd.DataFrame({'ID': subjects,'Time'times,'Outcome': outcomes,'Treatment': treatments,'Age': ages,'Baseline_Score': baselines,'Sex': sexes,'School_ID': schools,'Measurement_Date': dates    })# 保存示例数据    simple_data.to_excel(data_file, sheet_name='Simple_Dataset', index=False)print(f"已创建示例数据并保存到: {data_file}")# 数据清洗和转换simple_data['ID'] = simple_data['ID'].astype('category')simple_data['Time'] = pd.to_numeric(simple_data['Time'], errors='coerce')simple_data['Age'] = pd.to_numeric(simple_data['Age'], errors='coerce')simple_data['Sex'] = simple_data['Sex'].astype('category')simple_data['Treatment'] = simple_data['Treatment'].astype('category')simple_data['Baseline_Score'] = pd.to_numeric(simple_data['Baseline_Score'], errors='coerce')simple_data['School_ID'] = simple_data['School_ID'].astype('category')if'Measurement_Date'in simple_data.columns:    simple_data['Measurement_Date'] = pd.to_datetime(simple_data['Measurement_Date'], errors='coerce')simple_data['Outcome'] = pd.to_numeric(simple_data['Outcome'], errors='coerce')# 删除完全缺失Outcome的行simple_data = simple_data.dropna(subset=['Outcome'])# 查看数据结构print("\n数据集结构:")print(f"行数: {simple_data.shape[0]}, 列数: {simple_data.shape[1]}")print("\n数据摘要:")print(simple_data.describe())print("\n数据类型:")print(simple_data.dtypes)# 保存清洗后的数据simple_data.to_csv('清洗后数据.csv', index=False, encoding='utf-8-sig')# ==============================# 2. 探索性数据分析# ==============================print("\n2. 探索性数据分析...")# 创建图形文件夹fig_dir = results_dir / 'figures'fig_dir.mkdir(exist_ok=True)# 2.1 个体增长轨迹plt.figure(figsize=(12, 8))for subject_id in simple_data['ID'].unique()[:50]:  # 只显示前50个个体避免过度拥挤    subject_data = simple_data[simple_data['ID'] == subject_id]    plt.plot(subject_data['Time'], subject_data['Outcome'],             color='gray', alpha=0.3, linewidth=0.5)# 添加平滑曲线from scipy.interpolate import make_interp_splinetry:    time_sorted = simple_data['Time'].sort_values().unique()    mean_outcome_by_time = simple_data.groupby('Time')['Outcome'].mean().reindex(time_sorted)# 使用样条插值获得平滑曲线if len(time_sorted) > 3:        x_smooth = np.linspace(time_sorted.min(), time_sorted.max(), 300)        spl = make_interp_spline(time_sorted, mean_outcome_by_time.values, k=3)        y_smooth = spl(x_smooth)        plt.plot(x_smooth, y_smooth, color='red', linewidth=2, label='平均趋势')except Exception as e:print(f"平滑曲线绘制失败: {e}")plt.scatter(simple_data['Time'], simple_data['Outcome'],            alpha=0.2, s=10, color='blue')plt.title('个体增长轨迹图')plt.xlabel('时间点')plt.ylabel('结局变量')plt.grid(True, alpha=0.3)plt.savefig(fig_dir / '01_个体增长轨迹.png', dpi=300, bbox_inches='tight')plt.close()# 2.2 按治疗组分组的平均轨迹plt.figure(figsize=(12, 8))for treatment in simple_data['Treatment'].cat.categories:    treatment_data = simple_data[simple_data['Treatment'] == treatment]    mean_by_time = treatment_data.groupby('Time')['Outcome'].agg(['mean''std''count'])    mean_by_time['se'] = mean_by_time['std'] / np.sqrt(mean_by_time['count'])    plt.errorbar(mean_by_time.index, mean_by_time['mean'],                 yerr=1.96 * mean_by_time['se'],                 label=f'治疗组 {treatment}',                 capsize=5, linewidth=2, marker='o')plt.title('不同治疗组的平均增长轨迹')plt.xlabel('时间点')plt.ylabel('平均结局变量')plt.legend()plt.grid(True, alpha=0.3)plt.savefig(fig_dir / '02_治疗组平均轨迹.png', dpi=300, bbox_inches='tight')plt.close()
if len(individual_stats_df) > 0:    plt.figure(figsize=(10, 8))    plt.scatter(individual_stats_df['Intercept'],                individual_stats_df['Slope'],                alpha=0.6, s=50)# 添加回归线if len(individual_stats_df) > 1:        from scipy.stats import linregress        slope, intercept, r_value, p_value, std_err = linregress(            individual_stats_df['Intercept'],            individual_stats_df['Slope']        )        x_range = np.array([individual_stats_df['Intercept'].min(),                            individual_stats_df['Intercept'].max()])        plt.plot(x_range, intercept + slope * x_range,                 color='red', linewidth=2,                 label=f'回归线 (r={r_value:.3f})')        plt.legend()    plt.title('个体截距与斜率的关系')    plt.xlabel('截距(初始值)')    plt.ylabel('斜率(增长速率)')    plt.grid(True, alpha=0.3)    plt.savefig(fig_dir / '03_截距斜率关系.png', dpi=300, bbox_inches='tight')    plt.close()# 2.4 创建合并图fig, axes = plt.subplots(2, 2, figsize=(16, 12))# 子图1: 个体增长轨迹(简化版)for subject_id in simple_data['ID'].unique()[:30]:  # 只显示前30个    subject_data = simple_data[simple_data['ID'] == subject_id]    axes[0, 0].plot(subject_data['Time'], subject_data['Outcome'],                    color='gray', alpha=0.3, linewidth=0.5)axes[0, 0].scatter(simple_data['Time'], simple_data['Outcome'],                   alpha=0.1, s=5, color='blue')axes[0, 0].set_title('个体增长轨迹图')axes[0, 0].set_xlabel('时间点')axes[0, 0].set_ylabel('结局变量')axes[0, 0].grid(True, alpha=0.3)# 子图2: 治疗组平均轨迹for treatment in simple_data['Treatment'].cat.categories:    treatment_data = simple_data[simple_data['Treatment'] == treatment]    mean_by_time = treatment_data.groupby('Time')['Outcome'].mean()    axes[0, 1].plot(mean_by_time.index, mean_by_time.values,                    label=f'治疗组 {treatment}', linewidth=2, marker='o')axes[0, 1].set_title('不同治疗组的平均增长轨迹')axes[0, 1].set_xlabel('时间点')axes[0, 1].set_ylabel('平均结局变量')axes[0, 1].legend()axes[0, 1].grid(True, alpha=0.3)# 子图3: 截距斜率关系if len(individual_stats_df) > 0:    axes[1, 0].scatter(individual_stats_df['Intercept'],                       individual_stats_df['Slope'],                       alpha=0.6, s=50)    axes[1, 0].set_title('个体截距与斜率的关系')    axes[1, 0].set_xlabel('截距(初始值)')    axes[1, 0].set_ylabel('斜率(增长速率)')    axes[1, 0].grid(True, alpha=0.3)# 子图4: 数据分布axes[1, 1].hist(simple_data['Outcome'], bins=30, edgecolor='black', alpha=0.7)axes[1, 1].set_title('结局变量分布')axes[1, 1].set_xlabel('结局变量值')axes[1, 1].set_ylabel('频数')axes[1, 1].grid(True, alpha=0.3)plt.tight_layout()plt.savefig(fig_dir / '04_探索性数据分析合并图.png', dpi=300, bbox_inches='tight')plt.close()# ==============================# 3. 非线性混合效应模型准备# ==============================print("\n3. 准备非线性混合效应模型数据...")# 复制数据并创建新变量nlme_data = simple_data.copy()# 标准化连续变量scaler_age = StandardScaler()scaler_baseline = StandardScaler()nlme_data['Age_c'] = scaler_age.fit_transform(nlme_data[['Age']])nlme_data['Baseline_c'] = scaler_baseline.fit_transform(nlme_data[['Baseline_Score']])# 确保Treatment是分类变量并设置参考水平nlme_data['Treatment'] = pd.Categorical(nlme_data['Treatment'])nlme_data['Treatment'] = nlme_data['Treatment'].cat.reorder_categories(    sorted(nlme_data['Treatment'].cat.categories))# ==============================# 4. 指数增长模型拟合# ==============================print("\n4. 拟合指数增长模型...")def exponential_func(t, A, B):"""指数函数: y = A * exp(B * t)"""return A * np.exp(B * t)# 首先为每个个体拟合单独的指数模型,获取初始参数估计individual_params = []valid_subjects = []for subject_id in nlme_data['ID'].unique():    subject_data = nlme_data[nlme_data['ID'] == subject_id]if len(subject_data) >= 3:  # 需要足够的数据点        try:# 初始参数估计            A_init = subject_data['Outcome'].iloc[0]            B_init = 0.05# 拟合曲线            params, _ = curve_fit(exponential_func,                                  subject_data['Time'],                                  subject_data['Outcome'],                                  p0=[A_init, B_init],                                  maxfev=10000)            individual_params.append({'ID': subject_id,'A': params[0],'B': params[1]            })            valid_subjects.append(subject_id)        except:continueif len(individual_params) > 0:    param_df = pd.DataFrame(individual_params)print(f"成功拟合 {len(param_df)} 个个体的指数模型")# 使用平均参数作为整体模型的初始值    A_init_global = param_df['A'].median()    B_init_global = param_df['B'].median()print(f"全局初始参数: A={A_init_global:.2f}, B={B_init_global:.4f}")# 保存个体参数    param_df.to_csv('指数模型个体参数.csv', index=False, encoding='utf-8-sig')# 可视化个体拟合    plt.figure(figsize=(12, 8))# 随机选择几个个体显示    np.random.seed(123)    sample_ids = np.random.choice(valid_subjects, min(8, len(valid_subjects)), replace=False)for i, subject_id in enumerate(sample_ids):        subject_data = nlme_data[nlme_data['ID'] == subject_id]        subject_param = param_df[param_df['ID'] == subject_id].iloc[0]# 生成平滑曲线        t_smooth = np.linspace(subject_data['Time'].min(),                               subject_data['Time'].max(), 100)        y_smooth = exponential_func(t_smooth,                                    subject_param['A'],                                    subject_param['B'])        plt.subplot(2, 4, i + 1)        plt.scatter(subject_data['Time'], subject_data['Outcome'],                    alpha=0.7, s=30)        plt.plot(t_smooth, y_smooth, 'r-', linewidth=2)        plt.title(f'ID: {subject_id}')        plt.xlabel('时间')        plt.ylabel('结局变量')        plt.grid(True, alpha=0.3)    plt.suptitle('个体指数增长模型拟合', fontsize=16)    plt.tight_layout()    plt.savefig(fig_dir / '05_个体指数模型拟合.png', dpi=300, bbox_inches='tight')    plt.close()# 整体数据拟合(不考虑随机效应)    try:        all_times = nlme_data['Time'].values        all_outcomes = nlme_data['Outcome'].values        popt, pcov = curve_fit(exponential_func, all_times, all_outcomes,                               p0=[A_init_global, B_init_global],                               maxfev=10000)print(f"整体指数模型参数: A={popt[0]:.2f}, B={popt[1]:.4f}")# 可视化整体拟合        plt.figure(figsize=(10, 6))        plt.scatter(all_times, all_outcomes, alpha=0.1, s=10, label='原始数据')        t_smooth = np.linspace(all_times.min(), all_times.max(), 100)        y_smooth = exponential_func(t_smooth, popt[0], popt[1])        plt.plot(t_smooth, y_smooth, 'r-', linewidth=3, label='指数拟合')        plt.title('整体指数增长模型拟合')        plt.xlabel('时间')        plt.ylabel('结局变量')        plt.legend()        plt.grid(True, alpha=0.3)        plt.savefig(fig_dir / '06_整体指数模型拟合.png', dpi=300, bbox_inches='tight')        plt.close()        exp_model_success = True        exp_params = popt    except Exception as e:print(f"整体指数模型拟合失败: {e}")        exp_model_success = False        exp_params = Noneelse:print("没有足够的个体数据拟合指数模型")    exp_model_success = False    exp_params = None# ==============================# 5. 逻辑斯蒂增长模型拟合# ==============================print("\n5. 拟合逻辑斯蒂增长模型...")def logistic_func(t, Asym, xmid, scal):"""逻辑斯蒂函数: y = Asym / (1 + exp((xmid - t)/scal))"""return Asym / (1 + np.exp((xmid - t) / scal))# 尝试拟合逻辑斯蒂模型try:# 获取合理初始值    Asym_init = nlme_data['Outcome'].max() * 1.1  # 渐近线略大于最大值    xmid_init = nlme_data['Time'].median()  # 中点在中位数时间    scal_init = 1.0  # 尺度参数# 使用curve_fit拟合    popt_logistic, pcov_logistic = curve_fit(logistic_func,                                             nlme_data['Time'].values,                                             nlme_data['Outcome'].values,                                             p0=[Asym_init, xmid_init, scal_init],                                             maxfev=10000)print(f"逻辑斯蒂模型参数: Asym={popt_logistic[0]:.2f}, "          f"xmid={popt_logistic[1]:.2f}, scal={popt_logistic[2]:.2f}")# 可视化逻辑斯蒂拟合    plt.figure(figsize=(10, 6))    plt.scatter(nlme_data['Time'], nlme_data['Outcome'],                alpha=0.1, s=10, label='原始数据')    t_smooth = np.linspace(nlme_data['Time'].min(),                           nlme_data['Time'].max(), 100)    y_smooth = logistic_func(t_smooth, *popt_logistic)    plt.plot(t_smooth, y_smooth, 'g-', linewidth=3, label='逻辑斯蒂拟合')    plt.title('逻辑斯蒂增长模型拟合')    plt.xlabel('时间')    plt.ylabel('结局变量')    plt.legend()    plt.grid(True, alpha=0.3)    plt.savefig(fig_dir / '07_逻辑斯蒂模型拟合.png', dpi=300, bbox_inches='tight')    plt.close()    logistic_model_success = True    logistic_params = popt_logisticexcept Exception as e:print(f"逻辑斯蒂模型拟合失败: {e}")    logistic_model_success = False    logistic_params = None# ==============================# 6. 线性混合模型(二次增长模型)# ==============================print("\n6. 拟合线性混合模型(二次增长模型)...")# 准备数据mixed_data = nlme_data.copy()# 创建时间平方项mixed_data['Time_sq'] = mixed_data['Time'] ** 2# 创建虚拟变量(用于Treatment)mixed_data = pd.get_dummies(mixed_data, columns=['Treatment'], prefix='Treatment', drop_first=False)# 提取treatment列名treatment_cols = [col for col in mixed_data.columns if col.startswith('Treatment_')]# 构建混合模型公式# 基础固定效应base_formula = 'Outcome ~ Time + Time_sq + Age_c + Baseline_c'# 添加治疗组效应(避免虚拟变量陷阱)if len(treatment_cols) > 1:# 使用所有treatment列,但模型会自动处理多重共线性    treatment_formula = ' + '.join(treatment_cols)    formula = f'{base_formula} + {treatment_formula}'else:    formula = base_formula# 添加随机效应(随机截距和随机斜率)formula_with_random = f'{formula} + (1 + Time | ID)'print(f"模型公式: {formula_with_random}")try:# 使用statsmodels的MixedLM# 注意:statsmodels的MixedLM不支持复杂的随机效应结构如(1 + Time | ID)# 这里我们简化,只使用随机截距# 简化公式:只有随机截距    formula_simple = f'{formula}'# 为MixedLM准备数据# 我们需要为随机效应创建组变量    mixed_data['group'] = mixed_data['ID']# 拟合混合模型    from statsmodels.regression.mixed_linear_model import MixedLM# 准备设计矩阵    X = pd.get_dummies(mixed_data[['Time''Time_sq''Age_c''Baseline_c'] + treatment_cols],                       drop_first=True)    X = sm.add_constant(X)    y = mixed_data['Outcome']    groups = mixed_data['group']# 拟合模型    mixed_model = MixedLM(y, X, groups)    mixed_result = mixed_model.fit()print("混合模型拟合成功!")print(mixed_result.summary())# 提取固定效应    fixed_effects = mixed_result.params    fixed_se = mixed_result.bse# 计算t值和p值    t_values = fixed_effects / fixed_se    p_values = 2 * (1 - stats.t.cdf(np.abs(t_values), mixed_result.df_resid))# 创建固定效应表    fixed_table = pd.DataFrame({'参数': fixed_effects.index,'估计值': fixed_effects.values,'标准误': fixed_se.values,'t值': t_values.values,'p值': p_values.values    })# 添加显著性标记    conditions = [        fixed_table['p值'] < 0.001,        fixed_table['p值'] < 0.01,        fixed_table['p值'] < 0.05    ]    choices = ['***''**''*']    fixed_table['显著性'] = np.select(conditions, choices, default='')# 保存固定效应表    fixed_table.to_csv('08_混合模型固定效应.csv', index=False, encoding='utf-8-sig')# 提取随机效应    random_effects = mixed_result.random_effects    random_df = pd.DataFrame()for group, effects in random_effects.items():        temp_df = pd.DataFrame(effects, index=[group])        random_df = pd.concat([random_df, temp_df])    random_df.columns = ['随机截距']    random_df.to_csv('09_混合模型随机效应.csv', encoding='utf-8-sig')# 计算组内相关系数(ICC)# ICC = 组间方差 / (组间方差 + 组内方差)    try:# 提取方差成分        vc = mixed_result.cov_re.iloc[0, 0]  # 随机截距方差        residual_var = mixed_result.scale  # 残差方差        total_var = vc + residual_var        icc = vc / total_varprint(f"随机截距方差: {vc:.4f}")print(f"残差方差: {residual_var:.4f}")print(f"组内相关系数(ICC): {icc:.4f} ({icc * 100:.1f}%)")    except:        icc = None    quadratic_model_success = True    quadratic_model = mixed_resultexcept Exception as e:print(f"混合模型拟合失败: {e}")    import traceback    traceback.print_exc()    quadratic_model_success = False    quadratic_model = None# ==============================# 7. 模型比较# ==============================print("\n7. 模型比较...")model_comparison = []# 指数模型比较if exp_model_success and exp_params is not None:# 计算指数模型的拟合优度    y_true = nlme_data['Outcome'].values    y_pred_exp = exponential_func(nlme_data['Time'].values, exp_params[0], exp_params[1])# 计算残差平方和    rss_exp = np.sum((y_true - y_pred_exp) ** 2)    tss = np.sum((y_true - np.mean(y_true)) ** 2)    r_squared_exp = 1 - (rss_exp / tss)# 计算AIC和BIC(近似)    n_params_exp = 2  # A, B两个参数    n_obs = len(y_true)    aic_exp = n_obs * np.log(rss_exp / n_obs) + 2 * n_params_exp    bic_exp = n_obs * np.log(rss_exp / n_obs) + n_params_exp * np.log(n_obs)    model_comparison.append({'模型''指数增长模型','AIC': round(aic_exp, 2),'BIC': round(bic_exp, 2),'R²': round(r_squared_exp, 4),'参数个数': n_params_exp    })# 逻辑斯蒂模型比较if logistic_model_success and logistic_params is not None:    y_true = nlme_data['Outcome'].values    y_pred_logistic = logistic_func(nlme_data['Time'].values, *logistic_params)    rss_logistic = np.sum((y_true - y_pred_logistic) ** 2)    r_squared_logistic = 1 - (rss_logistic / tss)    n_params_logistic = 3  # Asym, xmid, scal    aic_logistic = n_obs * np.log(rss_logistic / n_obs) + 2 * n_params_logistic    bic_logistic = n_obs * np.log(rss_logistic / n_obs) + n_params_logistic * np.log(n_obs)    model_comparison.append({'模型''逻辑斯蒂模型','AIC': round(aic_logistic, 2),'BIC': round(bic_logistic, 2),'R²': round(r_squared_logistic, 4),'参数个数': n_params_logistic    })# 混合模型比较if quadratic_model_success and quadratic_model is not None:# 使用模型自带的AIC和BIC    aic_mixed = quadratic_model.aic    bic_mixed = quadratic_model.bic# 计算R²    y_pred_mixed = quadratic_model.fittedvalues    rss_mixed = np.sum((mixed_data['Outcome'] - y_pred_mixed) ** 2)    r_squared_mixed = 1 - (rss_mixed / tss)    n_params_mixed = len(quadratic_model.params) + 1  # 固定效应 + 随机效应方差    model_comparison.append({'模型''混合效应模型','AIC': round(aic_mixed, 2),'BIC': round(bic_mixed, 2),'R²': round(r_squared_mixed, 4),'参数个数': n_params_mixed    })# 创建比较表if model_comparison:    comparison_df = pd.DataFrame(model_comparison)    comparison_df = comparison_df.sort_values('AIC')    comparison_df.to_csv('10_模型比较.csv', index=False, encoding='utf-8-sig')print("\n模型比较结果:")print(comparison_df.to_string(index=False))# 选择最佳模型    best_model_name = comparison_df.iloc[0]['模型']print(f"\n最佳模型: {best_model_name} (AIC最低)")# 根据模型名称分配最佳模型if best_model_name == '指数增长模型':        best_model = {'type''exponential''params': exp_params}elif best_model_name == '逻辑斯蒂模型':        best_model = {'type''logistic''params': logistic_params}else:        best_model = {'type''mixed''model': quadratic_model}else:print("没有可比较的模型")    best_model = None    best_model_name = "无"# ==============================# 8. 模型可视化# ==============================print("\n8. 模型可视化...")if best_model is not None:# 8.1 总体拟合曲线    plt.figure(figsize=(12, 8))# 绘制原始数据点for treatment in nlme_data['Treatment'].cat.categories:        treatment_data = nlme_data[nlme_data['Treatment'] == treatment]        plt.scatter(treatment_data['Time'], treatment_data['Outcome'],                    alpha=0.3, s=20, label=f'治疗组 {treatment}')# 根据模型类型绘制拟合曲线    time_range = np.linspace(nlme_data['Time'].min(),                             nlme_data['Time'].max(), 100)if best_model['type'] == 'exponential':        y_fit = exponential_func(time_range, best_model['params'][0], best_model['params'][1])        plt.plot(time_range, y_fit, 'k-', linewidth=3, label='指数模型拟合')elif best_model['type'] == 'logistic':        y_fit = logistic_func(time_range, *best_model['params'])        plt.plot(time_range, y_fit, 'k-', linewidth=3, label='逻辑斯蒂模型拟合')elif best_model['type'] == 'mixed':# 为混合模型创建预测数据# 这里简化,使用平均协变量值        pred_data = pd.DataFrame({'Time': time_range,'Time_sq': time_range ** 2,'Age_c': 0,'Baseline_c': 0        })# 添加treatment列(使用参考组)for col in treatment_cols:            pred_data[col] = 0if'Treatment_A'in pred_data.columns:            pred_data['Treatment_A'] = 1# 添加常数项        pred_data['const'] = 1# 确保列顺序与模型一致        X_pred = pred_data[quadratic_model.params.index]# 预测        y_fit = quadratic_model.predict(X_pred)        plt.plot(time_range, y_fit, 'k-', linewidth=3, label='混合模型拟合')    plt.title(f'最佳模型拟合曲线 - {best_model_name}')    plt.xlabel('时间点')    plt.ylabel('结局变量')    plt.legend()    plt.grid(True, alpha=0.3)    plt.savefig(fig_dir / '11_最佳模型拟合曲线.png', dpi=300, bbox_inches='tight')    plt.close()# 8.2 个体预测曲线(随机选择8个个体)    np.random.seed(123)    sample_ids = np.random.choice(nlme_data['ID'].unique(),                                  min(8, len(nlme_data['ID'].unique())),                                  replace=False)    fig, axes = plt.subplots(2, 4, figsize=(16, 10))    axes = axes.flatten()for i, subject_id in enumerate(sample_ids):if i >= len(axes):break        subject_data = nlme_data[nlme_data['ID'] == subject_id]# 绘制个体数据点        axes[i].scatter(subject_data['Time'], subject_data['Outcome'],                        alpha=0.7, s=50)# 个体线性拟合(二次多项式)if len(subject_data) >= 3:            try:# 二次多项式拟合                coeffs = np.polyfit(subject_data['Time'], subject_data['Outcome'], 2)                poly_func = np.poly1d(coeffs)                t_smooth = np.linspace(subject_data['Time'].min(),                                       subject_data['Time'].max(), 50)                y_smooth = poly_func(t_smooth)                axes[i].plot(t_smooth, y_smooth, 'r-', linewidth=2)            except:                pass        axes[i].set_title(f'ID: {subject_id}')        axes[i].set_xlabel('时间点')        axes[i].set_ylabel('结局变量')        axes[i].grid(True, alpha=0.3)    plt.suptitle('个体增长曲线 (随机选择8个个体)', fontsize=16)    plt.tight_layout()    plt.savefig(fig_dir / '12_个体增长曲线.png', dpi=300, bbox_inches='tight')    plt.close()# 8.3 模型诊断图(针对混合模型)if best_model['type'] == 'mixed' and quadratic_model_success:# 残差分析        residuals = quadratic_model.resid        fitted_values = quadratic_model.fittedvalues        fig, axes = plt.subplots(2, 3, figsize=(15, 10))# 1. 残差与拟合值图        axes[0, 0].scatter(fitted_values, residuals, alpha=0.5)        axes[0, 0].axhline(y=0, color='r', linestyle='--')        axes[0, 0].set_xlabel('拟合值')        axes[0, 0].set_ylabel('残差')        axes[0, 0].set_title('残差图')        axes[0, 0].grid(True, alpha=0.3)# 2. Q-Q图        stats.probplot(residuals, dist="norm", plot=axes[0, 1])        axes[0, 1].set_title('Q-Q图')        axes[0, 1].grid(True, alpha=0.3)# 3. 残差直方图        axes[0, 2].hist(residuals, bins=30, edgecolor='black', alpha=0.7)        axes[0, 2].set_xlabel('残差')        axes[0, 2].set_ylabel('频数')        axes[0, 2].set_title('残差分布')        axes[0, 2].grid(True, alpha=0.3)# 4. 残差序列图        axes[1, 0].plot(residuals, 'b-', alpha=0.7)        axes[1, 0].axhline(y=0, color='r', linestyle='--')        axes[1, 0].set_xlabel('观察序号')        axes[1, 0].set_ylabel('残差')        axes[1, 0].set_title('残差序列图')        axes[1, 0].grid(True, alpha=0.3)# 5. 拟合值与观测值比较        axes[1, 1].scatter(fitted_values, mixed_data['Outcome'], alpha=0.5)# 添加对角线        min_val = min(fitted_values.min(), mixed_data['Outcome'].min())        max_val = max(fitted_values.max(), mixed_data['Outcome'].max())        axes[1, 1].plot([min_val, max_val], [min_val, max_val], 'r--')        axes[1, 1].set_xlabel('拟合值')        axes[1, 1].set_ylabel('观测值')        axes[1, 1].set_title('拟合值 vs 观测值')        axes[1, 1].grid(True, alpha=0.3)# 6. 残差自相关图        from statsmodels.graphics.tsaplots import plot_acf        plot_acf(residuals, lags=20, ax=axes[1, 2])        axes[1, 2].set_title('残差自相关')        plt.suptitle('混合模型诊断图', fontsize=16)        plt.tight_layout()        plt.savefig(fig_dir / '13_混合模型诊断图.png', dpi=300, bbox_inches='tight')        plt.close()# ==============================# 9. 交互效应分析# ==============================print("\n9. 交互效应分析...")# 如果混合模型拟合成功,分析交互效应if quadratic_model_success and quadratic_model is not None:    try:# 创建预测网格        time_values = np.linspace(nlme_data['Time'].min(),                                  nlme_data['Time'].max(), 50)        age_values = [-1, 0, 1]  # 标准化年龄值# 准备预测数据        predictions = []for age in age_values:for time in time_values:# 创建一行数据                row = {'Time': time,'Time_sq': time ** 2,'Age_c': age,'Baseline_c': 0,'const': 1                }# 添加treatment列for col in treatment_cols:                    row[col] = 0if'Treatment_A'in treatment_cols:                    row['Treatment_A'] = 1# 确保列顺序                df_row = pd.DataFrame([row])                X_row = df_row[quadratic_model.params.index]# 预测                pred = quadratic_model.predict(X_row).iloc[0]                predictions.append({'Time': time,'Age_c': age,'Treatment''A',  # 参考组'预测值': pred                })        pred_df = pd.DataFrame(predictions)# 创建交互效应图        plt.figure(figsize=(12, 8))for age_val in age_values:            age_data = pred_df[pred_df['Age_c'] == age_val]            plt.plot(age_data['Time'], age_data['预测值'],                     linewidth=2,                     label=f'年龄(Z分数)={age_val}')        plt.title('年龄对结局变量的影响')        plt.xlabel('时间点')        plt.ylabel('预测结局变量')        plt.legend()        plt.grid(True, alpha=0.3)        plt.savefig(fig_dir / '14_年龄交互效应.png', dpi=300, bbox_inches='tight')        plt.close()    except Exception as e:print(f"交互效应分析失败: {e}")# ==============================# 10. 创建Word报告# ==============================print("\n10. 创建Word分析报告...")# 创建Word文档doc = Document()# 添加标题title = doc.add_heading('非线性混合效应模型分析报告', 0)title.alignment = WD_ALIGN_PARAGRAPH.CENTER# 添加日期doc.add_paragraph(f'生成日期: {datetime.now().strftime("%Y年%m月%d日")}')doc.add_paragraph()# 1. 分析概述doc.add_heading('1. 分析概述', level=1)doc.add_paragraph('本报告展示了非线性混合效应模型(NLME)的分析结果。非线性混合效应模型用于分析纵向数据中响应变量与时间之间的非线性关系,同时考虑了数据的层次结构(个体内和个体间变异)。')doc.add_paragraph(    f'分析数据集包含 {len(nlme_data["ID"].unique())} 个个体,每个个体最多有 {int(nlme_data["Time"].max() + 1)} 个时间点的测量。')doc.add_paragraph()# 2. 探索性数据分析doc.add_heading('2. 探索性数据分析', level=1)doc.add_paragraph('下图展示了个体增长轨迹、不同治疗组的平均轨迹以及个体初始值与增长速率的关系。')# 插入探索性分析图try:    doc.add_picture(str(fig_dir / '04_探索性数据分析合并图.png'), width=Inches(6))except:    doc.add_paragraph('探索性分析图加载失败')doc.add_paragraph()# 3. 模型拟合与比较doc.add_heading('3. 模型拟合与比较', level=1)doc.add_paragraph('我们比较了以下几种模型:')doc.add_paragraph('• 指数增长模型: Y = A × exp(B × Time)', style='List Bullet')doc.add_paragraph('• 逻辑斯蒂增长模型: Y = Asym / (1 + exp((xmid - Time)/scal))', style='List Bullet')doc.add_paragraph('• 混合效应模型: 包含时间和时间平方项的混合效应模型', style='List Bullet')doc.add_paragraph('模型比较结果如下表所示:')# 添加模型比较表if'comparison_df'in locals():# 创建表格    table = doc.add_table(rows=len(comparison_df) + 1, cols=len(comparison_df.columns))    table.style = 'Light Grid Accent 1'# 添加表头    header_cells = table.rows[0].cellsfor i, col in enumerate(comparison_df.columns):        header_cells[i].text = str(col)# 添加数据行for i, row in comparison_df.iterrows():        row_cells = table.rows[i + 1].cellsfor j, value in enumerate(row):            row_cells[j].text = str(value)    doc.add_paragraph()    doc.add_paragraph(f'根据AIC准则,最佳模型为:{best_model_name}')    doc.add_paragraph()# 4. 最佳模型结果doc.add_heading(f'4. 最佳模型结果 ({best_model_name})', level=1)if best_model is not None:if best_model['type'] == 'mixed' and quadratic_model_success:        doc.add_paragraph('模型固定效应参数估计:')# 创建固定效应表if'fixed_table'in locals():            table_fixed = doc.add_table(rows=len(fixed_table) + 1, cols=len(fixed_table.columns))            table_fixed.style = 'Light Grid Accent 1'# 添加表头            header_cells = table_fixed.rows[0].cellsfor i, col in enumerate(fixed_table.columns):                header_cells[i].text = str(col)# 添加数据行for i, row in fixed_table.iterrows():                row_cells = table_fixed.rows[i + 1].cellsfor j, value in enumerate(row):                    row_cells[j].text = str(value)            doc.add_paragraph()# 解释显著参数if'fixed_table'in locals():                sig_params = fixed_table[fixed_table['p值'] < 0.05]if len(sig_params) > 0:                    doc.add_paragraph('显著效应解释:')for _, param in sig_params.iterrows():                        param_name = param['参数']                        estimate = param['估计值']                        p_value = param['p值']if'Treatment'in param_name:                            doc.add_paragraph(                                f'• {param_name}的效应为{estimate:.3f} (p={p_value:.4f}),表明该治疗组相对于参照组有显著差异',                                style='List Bullet')elif'Age'in param_name:                            doc.add_paragraph(                                f'• 年龄效应为{estimate:.3f} (p={p_value:.4f}),表明年龄对结局变量有显著影响',                                style='List Bullet')elif'Baseline'in param_name:                            doc.add_paragraph(                                f'• 基线得分效应为{estimate:.3f} (p={p_value:.4f}),表明基线水平对结局变量有显著影响',                                style='List Bullet')elif'Time'in param_name:                            doc.add_paragraph(                                f'• 时间效应为{estimate:.3f} (p={p_value:.4f}),表明时间对结局变量有显著影响',                                style='List Bullet')# 随机效应解释        doc.add_paragraph('随机效应解释:')if'icc'in locals() and icc is not None:            doc.add_paragraph(                f'• 个体间变异占总变异的{icc * 100:.1f}% (ICC={icc:.3f}),表明个体特征对结局变量有重要影响。',                style='List Bullet')else:        doc.add_paragraph(f'{best_model_name}的参数估计:')if best_model['type'] == 'exponential':            doc.add_paragraph(f'• A = {best_model["params"][0]:.3f}')            doc.add_paragraph(f'• B = {best_model["params"][1]:.3f}')elif best_model['type'] == 'logistic':            doc.add_paragraph(f'• Asym = {best_model["params"][0]:.3f}')            doc.add_paragraph(f'• xmid = {best_model["params"][1]:.3f}')            doc.add_paragraph(f'• scal = {best_model["params"][2]:.3f}')# 5. 模型可视化doc.add_heading('5. 模型可视化', level=1)doc.add_paragraph('总体拟合曲线展示了最佳模型对数据的拟合情况:')# 插入总体拟合图try:    doc.add_picture(str(fig_dir / '11_最佳模型拟合曲线.png'), width=Inches(6))except:    doc.add_paragraph('总体拟合图加载失败')doc.add_paragraph('个体增长曲线展示了特定个体的增长模式:')# 插入个体拟合图try:    doc.add_picture(str(fig_dir / '12_个体增长曲线.png'), width=Inches(6))except:    doc.add_paragraph('个体拟合图加载失败')# 6. 模型诊断doc.add_heading('6. 模型诊断', level=1)doc.add_paragraph('模型诊断图检查模型假设是否满足:')# 插入诊断图try:if best_model['type'] == 'mixed':        doc.add_picture(str(fig_dir / '13_混合模型诊断图.png'), width=Inches(6))except:    doc.add_paragraph('诊断图加载失败')# 7. 公共卫生意义doc.add_heading('7. 公共卫生意义', level=1)doc.add_paragraph('非线性混合效应模型在公共卫生研究中的应用:')doc.add_paragraph('1. 药代动力学研究:描述药物在个体体内的血药浓度-时间曲线(常为指数衰减),并研究肝肾功能对曲线参数的影响。',    style='List Bullet')doc.add_paragraph('2. 疾病进展建模:描述疾病(如HIV感染后CD4细胞计数)的非线性变化轨迹,识别进展的关键时间点。',                  style='List Bullet')doc.add_paragraph('3. 生长曲线分析:研究儿童生长发育的非线性模式,识别生长突增期和稳定期。', style='List Bullet')doc.add_paragraph('4. 干预效果评估:评估公共卫生干预措施的非线性效果,识别效果最大化的关键时间窗口。', style='List Bullet')doc.add_paragraph()# 8. 结论doc.add_heading('8. 结论', level=1)doc.add_paragraph('本次分析成功拟合了非线性混合效应模型,并识别了影响结局变量的关键因素。主要发现包括:')if best_model is not None:if best_model['type'] == 'mixed' and 'fixed_table'in locals():        sig_params = fixed_table[fixed_table['p值'] < 0.05]if len(sig_params) > 0:            doc.add_paragraph('• 发现以下因素对结局变量有显著影响:')for i, (_, param) in enumerate(sig_params.iterrows()):if i < 3:  # 只显示前3个                    doc.add_paragraph(f'  - {param["参数"]}: 效应值 = {param["估计值"]:.3f} (p = {param["p值"]:.4f})')if'icc'in locals() and icc is not None:        doc.add_paragraph(f'• 个体间差异解释了总变异的{icc * 100:.1f}%')doc.add_paragraph('• 混合效应模型成功捕捉了数据中的增长模式,为理解个体发展轨迹提供了有力工具。')doc.add_paragraph()doc.add_paragraph('--- 报告结束 ---')# 保存Word文档report_file = '15_非线性混合效应模型分析报告.docx'doc.save(report_file)print(f"\n分析完成!结果已保存到文件夹: {results_dir}")print(f"Word报告已生成: {report_file}")print("\n生成的文件包括:")print("1. 清洗后数据.csv - 清洗后的数据集")print("2. figures/文件夹 - 所有可视化图表")print("3. 指数模型个体参数.csv - 个体指数模型参数")print("4. 混合模型固定效应.csv - 固定效应估计")print("5. 混合模型随机效应.csv - 随机效应估计")print("6. 模型比较.csv - 模型比较结果")print("7. 非线性混合效应模型分析报告.docx - 完整分析报告")print("\n=== 非线性混合效应模型分析完成 ===")# 保存分析日志log_content = f"""分析日志========分析时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}数据来源: {data_file}数据规模: {simple_data.shape[0]} 行, {simple_data.shape[1]} 列个体数量: {len(simple_data['ID'].unique())}时间点范围: {simple_data['Time'].min()} 到 {simple_data['Time'].max()}治疗组: {', '.join(sorted(simple_data['Treatment'].cat.categories))}模型拟合结果:------------指数模型: {'成功' if exp_model_success else '失败'}逻辑斯蒂模型: {'成功' if logistic_model_success else '失败'}混合效应模型: {'成功' if quadratic_model_success else '失败'}最佳模型: {best_model_name}分析完成!"""with open('分析日志.txt''w', encoding='utf-8') as f:    f.write(log_content)

纵向数据是指在多个时间点对同一组个体进行的重复测量。

1    混合效应模型Mixed Effects ModelMEM

2 固定效应模型 Fixed Effects Model FEM

3 多层线性模型 Hierarchical Linear Model HLM

4 广义估计方程 Generalized Estimating Equations GEE

5 广义线性混合模型 Generalized Linear Mixed Models GLMM

6 潜变量增长曲线模型 Latent Growth Curve Model LGCM

7 组轨迹模型 Group-Based Trajectory Model GBTM

8 交叉滞后模型 Cross-lagged (Panel) Model CLPM

9 重复测量方差分析 Repeated Measures ANOVA / MANOVA RM-ANOVA / RM-MANOVA

10 非线性混合效应模型 Nonlinear Mixed-Effects Models NLME

11 联合模型     Joint Models     JM

12 结构方程模型 Structural Equation Modeling SEM

13 广义相加模型 Generalized Additive Models GAM

14 潜类别模型 Latent Class Models LCM

15 潜剖面模型 Latent Profile Analysis LPA

16 状态空间模型 State Space Models SSM

17 纵向因子分析 Longitudinal Factor Analysis LFA

18 贝叶斯纵向模型 Bayesian Longitudinal Models - (Bayesian Models)

19 混合效应随机森林 Mixed Effects Random Forest MERF

20 纵向梯度提升 Longitudinal Gradient Boosting - (Longitudinal GBM)

21 K均值纵向聚类 K-means Longitudinal Clustering - (DTW-KMeans)

22   基于模型的聚类 Model-Based ClusteringMB-CLUST

医学统计数据分析分享交流SPSS、R语言、Python、ArcGis、Geoda、GraphPad、数据分析图表制作等心得。承接数据分析,论文返修,医学统计,机器学习,生存分析,空间分析,问卷分析业务。若有投稿和数据分析代做需求,可以直接联系我,谢谢!

!!!可加我粉丝群!!!

“医学统计数据分析”公众号右下角;

找到“联系作者”,

可加我微信,邀请入粉丝群!

【医学统计数据分析】工作室“粉丝群”
01
【临床】粉丝群

有临床流行病学数据分析

如(t检验、方差分析、χ2检验、logistic回归)、

(重复测量方差分析与配对T检验、ROC曲线)、

(非参数检验、生存分析、样本含量估计)、

(筛检试验:灵敏度、特异度、约登指数等计算)、

(绘制柱状图、散点图、小提琴图、列线图等)、

机器学习、深度学习、生存分析

等需求的同仁们,加入【临床】粉丝群

02
【公卫】粉丝群

疾控,公卫岗位的同仁,可以加一下【公卫】粉丝群,分享生态学研究、空间分析、时间序列、监测数据分析、时空面板技巧等工作科研自动化内容。

03
【生信】粉丝群

有实验室数据分析需求的同仁们,可以加入【生信】粉丝群,交流NCBI(基因序列)、UniProt(蛋白质)、KEGG(通路)、GEO(公共数据集)等公共数据库、基因组学转录组学蛋白组学代谢组学表型组学等数据分析和可视化内容。

或者可扫码直接加微信进群!!!

精品视频课程-“医学统计数据分析”视频号付费合集

“医学统计数据分析”视频号-付费合集兑换相应课程后,获取课程理论课PPT、代码、基础数据等相关资料,请大家在【医学统计数据分析】公众号右下角,找到“联系作者”,加我微信后打包发送。感谢您的支持!!

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-03-27 09:55:59 HTTP/2.0 GET : https://f.mffb.com.cn/a/482412.html
  2. 运行时间 : 0.093699s [ 吞吐率:10.67req/s ] 内存消耗:5,170.76kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=ae7c4bcec51da5e71e28eae49f556d5b
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000487s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000781s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000301s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000290s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000480s ]
  6. SELECT * FROM `set` [ RunTime:0.000190s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000534s ]
  8. SELECT * FROM `article` WHERE `id` = 482412 LIMIT 1 [ RunTime:0.001565s ]
  9. UPDATE `article` SET `lasttime` = 1774576560 WHERE `id` = 482412 [ RunTime:0.014723s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000325s ]
  11. SELECT * FROM `article` WHERE `id` < 482412 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000517s ]
  12. SELECT * FROM `article` WHERE `id` > 482412 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.002389s ]
  13. SELECT * FROM `article` WHERE `id` < 482412 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000757s ]
  14. SELECT * FROM `article` WHERE `id` < 482412 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000935s ]
  15. SELECT * FROM `article` WHERE `id` < 482412 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000907s ]
0.095384s