基于胎儿Y染色体浓度的孕周与BMI建模分析

摘要

本文利用某竞赛提供的胎儿Y染色体浓度数据,建立了以孕周和孕妇BMI为自变量的多项式回归模型,探讨了其对Y染色体浓度的影响。通过数据清洗与筛选,共获得1082条有效男胎样本。结果显示:Y染色体浓度随孕周显著上升,BMI对浓度也存在非线性效应。嵌套F检验表明引入BMI及其二次项显著提升模型拟合效果(p < 0.001)。该研究为无创产前检测(NIPT)中合理确定检测时机与人群分层提供了方法学依据。

1 引言

胎儿游离DNA浓度是无创产前检测准确性的关键指标。既往研究表明,胎儿Y染色体浓度与孕周呈正相关,但不同孕妇个体特征(如BMI)可能影响该关系。本文基于竞赛公开数据,采用数理建模方法,系统分析孕周、BMI与Y染色体浓度之间的关系,并探索BMI分组与检测时点优化的可行性。

2 数据与方法

2.1 数据来源与处理

原始数据为某医疗检测机构提供的临床检测记录,包含孕周、孕妇BMI、Y染色体浓度等指标。

  • 孕周解析:如“12+3”统一转化为12.43周。

  • 男胎判定:若Y浓度或Y染色体Z值非空,即判定为男胎。

  • 浓度统一:将Y染色体浓度统一转换为比例数值(0–1区间)。

最终筛选得到1082例男胎样本。

Step 1|读取数据与字段检查
# Step 1:读取 Excel & 初步字段核对
import pandas as pd
from pathlib import PathDATA_XLSX = Path("附件.xlsx")  # ←改成你的路径xls = pd.ExcelFile(DATA_XLSX)
sheet_name = xls.sheet_names[0]       # 默认第一张表
df_raw = pd.read_excel(DATA_XLSX, sheet_name=sheet_name)
df_raw.columns = [str(c).strip() for c in df_raw.columns]print("工作表:", sheet_name)
print("列名:", list(df_raw.columns))
df_raw.head(10)

Step 2|数据清洗与派生字段
# Step 2:数据清洗与派生
import numpy as np
import redf = df_raw.copy()def parse_gest_week(x):"""将 '12+3'/'12周+3天'/12 等解析为“周”的浮点数。"""if pd.isna(x):return np.nanif isinstance(x, (int, float)):return float(x)s = str(x)m = re.search(r'(\d+)\D+(\d+)', s)   # 有“周+天”的情况if m:w = float(m.group(1)); d = float(m.group(2))return w + d/7.0m = re.search(r'(\d+)', s)           # 只有周if m:return float(m.group(1))return np.nan# 标准化字段
df["孕周_周"]  = df["检测孕周"].apply(parse_gest_week)
df["BMI"]     = pd.to_numeric(df["孕妇BMI"], errors="coerce")
df["Y浓度_raw"] = pd.to_numeric(df["Y染色体浓度"], errors="coerce")
df["ZY"]      = pd.to_numeric(df["Y染色体的Z值"], errors="coerce")# 男胎判定(保守):Y浓度 或 ZY 任一非空
is_male = df["Y浓度_raw"].notna() | df["ZY"].notna()# 量纲判断:若>1 的比例 >50%,视为百分数(如 7 表示 7%)
gt1_ratio = (df.loc[is_male, "Y浓度_raw"] > 1).mean()
df["Y浓度"] = (df["Y浓度_raw"]/100.0) if gt1_ratio > 0.5 else df["Y浓度_raw"].astype(float)# 建模子集:三要素齐全
df_model = df.loc[is_male].copy()
df_model = df_model[df_model["孕周_周"].notna() & df_model["BMI"].notna() & df_model["Y浓度"].notna()
].copy()summary = pd.DataFrame([{"总样本数": len(df),"男胎样本数(判定)": int(is_male.sum()),"用于建模样本数": len(df_model),"孕周均值": round(df_model["孕周_周"].mean(), 3),"孕周范围": f'{df_model["孕周_周"].min():.1f} ~ {df_model["孕周_周"].max():.1f}',"BMI均值": round(df_model["BMI"].mean(), 3),"BMI范围": f'{df_model["BMI"].min():.1f} ~ {df_model["BMI"].max():.1f}',"Y浓度是否多数为百分数": bool(gt1_ratio > 0.5),"Y浓度均值(比例)": round(df_model["Y浓度"].mean(), 4)
}])
summary.to_csv(OUT_DIR/"Step2_清洗后样本摘要.csv", index=False, encoding="utf-8-sig")
summary

2.2 探索性分析

  • 绘制孕周与Y浓度散点图,观察非线性趋势。

  • 计算控制孕周后的残差与BMI的相关性。

  • 对比不同BMI分组下的Y浓度分布。

# Step 3:EDA 可视化(中文无乱码)
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeaturesdef savefig(path):plt.tight_layout()plt.savefig(path, dpi=160)plt.close()# 3-1 直方图:孕周、BMI、Y浓度
for col, title in [("孕周_周","孕周(周)分布"), ("BMI","BMI 分布"), ("Y浓度","Y浓度(比例)分布")]:plt.figure()plt.hist(df_model[col].values, bins=30)plt.xlabel(title); plt.ylabel("频数"); plt.title(title)savefig(OUT_DIR / f"Step3_{col}_hist.png")# 3-2 散点 + 二次拟合:Y vs 孕周(只看形状)
GA = df_model["孕周_周"].astype(float).values
Y  = df_model["Y浓度"].astype(float).valuesplt.figure()
plt.scatter(GA, Y, alpha=0.6)
coefs = np.polyfit(GA, Y, deg=2)
xx = np.linspace(np.nanmin(GA), np.nanmax(GA), 200)
yy = np.polyval(coefs, xx)
plt.plot(xx, yy, linewidth=2)
plt.xlabel("孕周(周)"); plt.ylabel("Y染色体浓度(比例)"); plt.title("Y浓度 vs 孕周(二次拟合)")
savefig(OUT_DIR / "Step3_Y_vs_GA_quadratic.png")# 3-3 控制孕周后的残差 vs BMI(仅孕周二次项拟合)
pf = PolynomialFeatures(degree=2, include_bias=False)
X_ga = pf.fit_transform(GA.reshape(-1,1))
lr = LinearRegression().fit(X_ga, Y)
resid = Y - lr.predict(X_ga)plt.figure()
plt.scatter(df_model["BMI"].values, resid, alpha=0.6)
plt.axhline(0, linestyle="--")
plt.xlabel("BMI"); plt.ylabel("残差(仅以孕周拟合后的误差)")
plt.title("BMI 与 残差关系(控制孕周后)")
savefig(OUT_DIR / "Step3_resid_vs_BMI.png")

2.3 模型构建

设孕周为 ,BMI为 ,Y浓度为 。构建二次多项式模型:

采用最小二乘法估计参数,并通过嵌套F检验比较基线模型(仅含孕周二次项)与完整模型。

# Step 4:模型对比(嵌套F检验)
import statsmodels.api as sm
import pandas as pdGA = df_model["孕周_周"].astype(float).values
BMI = df_model["BMI"].astype(float).values
Y  = df_model["Y浓度"].astype(float).values# 简化模型:const + GA + GA^2
X1 = pd.DataFrame({"const": 1.0, "GA": GA})
X1["GA^2"] = X1["GA"]**2
m1 = sm.OLS(Y, X1.values).fit()# 完整模型:const + GA + BMI + GA^2 + GA*BMI + BMI^2
X2 = pd.DataFrame({"const": 1.0, "GA": GA, "BMI": BMI})
X2["GA^2"] = X2["GA"]**2
X2["GA*BMI"] = X2["GA"] * X2["BMI"]
X2["BMI^2"] = X2["BMI"]**2
m2 = sm.OLS(Y, X2.values).fit()fstat, fpval, df_diff = m2.compare_f_test(m1)model_compare = pd.DataFrame([{"简化模型_R2(仅孕周二次)": round(float(m1.rsquared), 4),"完整模型_R2(加BMI及交互二次)": round(float(m2.rsquared), 4),"嵌套F统计量": round(float(fstat), 4),"p值": fpval,"自由度差": int(df_diff)
}])
model_compare.to_csv(OUT_DIR/"Step4_模型对比.csv", index=False, encoding="utf-8-sig")
model_compare

2.4 模型评估

  • 使用5折交叉验证计算平均 。

  • 绘制残差图、QQ图检验正态性与异方差性。

  • 针对阈值浓度(4%),反解预测方程以估计不同BMI下的“最早达标孕周”。

# Step 5:完整模型系数与显著性 + 文本报告
coef_table = pd.DataFrame({"变量": ["const","GA","BMI","GA^2","GA*BMI","BMI^2"],"系数": list(m2.params),"p值": list(m2.pvalues)
})
coef_table_rounded = coef_table.copy()
coef_table_rounded["系数"] = coef_table_rounded["系数"].round(8)
coef_table_rounded.to_csv(OUT_DIR/"Step5_完整模型_系数与显著性.csv", index=False, encoding="utf-8-sig")with open(OUT_DIR/"Step5_完整模型_OLS报告.txt", "w", encoding="utf-8") as f:f.write(m2.summary2().as_text())coef_table_rounded

3 结果

3.1 样本特征

  • 孕周均值:16.85周(范围11–29周);

  • BMI均值:32.29(范围20.7–46.9);

  • Y浓度均值:7.7%(范围1%–23%)。

3.2 回归结果

模型估计系数如下:

  • 孕周一次项显著(p≈0.048);

  • BMI二次项显著(p≈0.006),呈“先升后降”趋势;

  • BMI与孕周交互项未显著。

嵌套F检验:加入BMI项后模型拟合度显著提升(p < 1e-8)。 5折交叉验证 ,提示模型可解释部分变异。

# Step 6:5折交叉验证
import numpy as np
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import KFold, cross_val_scoreX = df_model[["孕周_周","BMI"]].astype(float).values
y = df_model["Y浓度"].astype(float).valuespipe = make_pipeline(PolynomialFeatures(degree=2, include_bias=False),StandardScaler(with_mean=False),LinearRegression()
)cv = KFold(n_splits=5, shuffle=True, random_state=42)
r2_cv = cross_val_score(pipe, X, y, cv=cv, scoring="r2")cv_table = pd.DataFrame([{"5折CV_R2_均值": float(np.mean(r2_cv)),"5折CV_R2_STD": float(np.std(r2_cv))
}])
cv_table.to_csv(OUT_DIR/"Step6_5折CV_R2.csv", index=False, encoding="utf-8-sig")
cv_table

3.3 可视化结果

  • 孕周与Y浓度曲线:非线性上升趋势明显。

  • 不同BMI预测曲线:高BMI组整体推迟达标孕周。

  • 模型诊断:残差大致符合正态,异方差性有限。

# Step 7:分层预测曲线(中文标签)
import numpy as np
import matplotlib.pyplot as pltcoef = dict(zip(["const","GA","BMI","GA^2","GA*BMI","BMI^2"], m2.params))def predict_y(ga, bmi):return (coef["const"]+ coef["GA"]*ga+ coef["BMI"]*bmi+ coef["GA^2"]*ga*ga+ coef["GA*BMI"]*ga*bmi+ coef["BMI^2"]*bmi*bmi)xx = np.linspace(GA.min(), GA.max(), 200)
bmi_levels = [28, 32, 36, 40]plt.figure()
for b in bmi_levels:yy = [predict_y(g, b) for g in xx]plt.plot(xx, yy, label=f"BMI={b}")
plt.axhline(0.04, linestyle="--")
plt.xlabel("孕周(周)"); plt.ylabel("预测Y浓度(比例)")
plt.title("不同BMI下:预测Y浓度-孕周曲线(完整模型)")
plt.legend()
plt.tight_layout()
plt.savefig(OUT_DIR / "Step7_不同BMI_预测曲线.png", dpi=160)
plt.close()

4 结论

结果表明,孕周是影响胎儿Y浓度的主要因素,而BMI对浓度存在非线性调节作用。对于BMI偏高的孕妇,可能需要更晚的孕周才能达到NIPT所需的最低浓度阈值。这与临床观察一致。研究发现:孕周显著正向影响浓度,BMI具有非线性效应。该模型可为NIPT检测时机与分层策略提供量化参考。

4.1模型诊断

# Step 8:模型诊断
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.stats.diagnostic import het_breuschpagany_hat = m2.fittedvalues
resid  = m2.resid# 8-1 残差 vs 拟合值
plt.figure()
plt.scatter(y_hat, resid, alpha=0.6)
plt.axhline(0, linestyle="--")
plt.xlabel("拟合值"); plt.ylabel("残差")
plt.title("残差 vs 拟合值(完整模型)")
plt.tight_layout()
plt.savefig(OUT_DIR / "Step8_残差_vs_拟合值.png", dpi=160)
plt.close()# 8-2 QQ 图
fig = sm.qqplot(resid, line='45', fit=True)
plt.title("QQ图(残差)")
plt.tight_layout()
plt.savefig(OUT_DIR / "Step8_QQPlot_残差.png", dpi=160)
plt.close()# 8-3 异方差检验(Breusch-Pagan)
exog = X2.values
bp_stat, bp_pval, _, _ = het_breuschpagan(resid, exog)
bp_table = pd.DataFrame([{"BP统计量": float(bp_stat), "BP_p值": float(bp_pval)}])
bp_table.to_csv(OUT_DIR/"Step8_BP异方差检验.csv", index=False, encoding="utf-8-sig")
bp_table

异方差性检验(BP检验)
  • BP统计量:46.39,p值≈7.6e-09

  • 结论:p值远小于0.05,说明残差存在显著的异方差性。即不同拟合值范围下残差方差不均一,违反了经典OLS假设。

残差 vs 拟合值图

  • 图像特点:
    • 残差大部分集中在0附近,但随着拟合值增大,残差的离散程度明显增大。

    • 出现了典型的“喇叭口”现象,进一步佐证了异方差问题。

  • 启示:说明模型预测在Y浓度较低区间比较稳定,但在较高区间波动较大,可能受BMI或其他未观测变量影响。

QQ图(残差正态性检验)

  • 图像特点:
    • 残差大部分点贴近对角线,表明残差整体分布接近正态。

    • 在尾部(特别是右上角),点明显偏离直线,说明残差存在重尾分布,即极端值比正态分布下更多。

  • 启示:模型正态性大致可接受,但尾部偏离提示少数极端样本可能对回归有较大影响。

残差基本居中,正态性大致成立,说明模型能捕捉主要趋势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/95859.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/95859.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/95859.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyTorch DDP 随机卡死复盘:最后一个 batch 挂起,NCCL 等待不返回

PyTorch DDP 随机卡死复盘&#xff1a;最后一个 batch 挂起&#xff0c;NCCL 等待不返回&#xff0c;三步修复 Sampler & drop_last很多人在接触深度学习的过程往往都是从自己的笔记本开始的&#xff0c;但是从接触工作后&#xff0c;更多的是通过分布式的训练来模型。由于…

计算机专业考研备考建议

对于全国硕士研究生招生考试&#xff08;考研&#xff09;&#xff0c;考试科目主要由两大部分组成&#xff1a;全国统一命题的公共课 和 由招生单位自主命题的专业课。具体的考试科目取决于你报考的专业和学校。下面我为你详细拆解&#xff1a;一、考试科目构成&#xff08;绝…

关于嵌入式学习——单片机1

基础整体概念以应用为中心:消费电子(手机、蓝牙耳机、智能音响)、医疗电子(心率脉搏、呼吸机)、无人机(大疆D)、机器人(人形四足机器人) 计算机技术:计算机五大组成:运算器(数据运算)、控制器(指令控制)、存储器(内存外存)、输入设备(鼠标、键盘、摄像头)、输出设备(显示器)软件…

LightDock.server liunx 双跑比较

LightDock: a new multi-scale approach to protein–protein docking The LightDock server is free and open to all users and there is no login requirement server 1示例 故去除约束 next step 结果有正有负合理 2.常见警告⚠ Structure contains HETATM entries. P…

SQL面试题及详细答案150道(61-80) --- 多表连接查询篇

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。 前后端面试题-专栏总目录 文章目录 一、本文面试题目录 61. 什么是内连接(INNE…

【实操】Noej4图数据库安装和mysql表衔接实操

目录 一、图数据库介绍 二、安装Neo4j 2.1 安装java环境 2.2 安装 Neo4j&#xff08;社区版&#xff09; 2.3 修改配置 2.4 验证测试 2.5 卸载 2.6 基本用法 2.7 windows连接服务器可视化 三、neo4j和mysql对比 3.1 场景对比 3.2 Mysql和neo4j的映射对比 3.3 mys…

【mysql】SQL查询全解析:从基础分组到高级自连接技巧

SQL查询全解析&#xff1a;从基础分组到高级自连接技巧详解玩家首次登录查询的多种实现方式与优化技巧在数据库查询中&#xff0c;同一个需求往往有多种实现方式。本文将通过"查询每个玩家第一次登录的日期"这一常见需求&#xff0c;深入解析SQL查询的多种实现方法&a…

MySQL常见报错分析及解决方案总结(9)---出现interactive_timeout/wait_timeout

关于超时报错&#xff0c;一共有五种超时参数&#xff0c;详见&#xff1a;MySQL常见报错分析及解决方案总结(7)---超时参数connect_timeout、interactive_timeout/wait_timeout、lock_wait_timeout、net等-CSDN博客 以下是当前报错的排查方法和解决方案&#xff1a; MySQL 中…

第13章 Jenkins性能优化

13.1 性能优化概述 性能问题识别 常见性能瓶颈&#xff1a; Jenkins性能问题分类&#xff1a;1. 系统资源瓶颈- CPU使用率过高- 内存不足或泄漏- 磁盘I/O瓶颈- 网络带宽限制2. 应用层面问题- JVM配置不当- 垃圾回收频繁- 线程池配置问题- 数据库连接池不足3. 架构设计问题- 单点…

Python+DRVT 从外部调用 Revit:批量创建梁

今天让我们继续&#xff0c;看看如何批量创建常用的基础元素&#xff1a;梁。 跳过轴线为直线段形的&#xff0c;先从圆弧形的开始&#xff1a; from typing import List, Tuple import math # drvt_pybind 支持多会话、多文档&#xff0c;先从简单的单会话、单文档开始 # My…

水上乐园票务管理系统设计与开发(代码+数据库+LW)

摘 要 随着旅游业的蓬勃发展&#xff0c;水上乐园作为夏日娱乐的重要组成部分&#xff0c;其票务管理效率和服务质量直接影响游客体验。然而&#xff0c;传统的票务管理模式往往面临信息更新不及时、服务响应慢等问题。因此&#xff0c;本研究旨在通过设计并实现一个基于Spri…

【前端教程】JavaScript DOM 操作实战案例详解

案例1&#xff1a;操作div子节点并修改样式与内容 功能说明 获取div下的所有子节点&#xff0c;设置它们的背景颜色为红色&#xff1b;如果是p标签&#xff0c;将其内容设置为"我爱中国"。 实现代码 <!DOCTYPE html> <html> <head><meta ch…

qiankun+vite+react配置微前端

微前端框架&#xff1a;qiankun。 主应用&#xff1a;react19vite7&#xff0c;子应用1&#xff1a;react19vite7&#xff0c;子应用2 &#xff1a;react19vite7 一、主应用 1. 安装依赖 pnpm i qiankun 2. 注册子应用 (1) 在src目录下创建个文件夹&#xff0c;用来存储关于微…

git: 取消文件跟踪

场景&#xff1a;第一次初始化仓库的时候没有忽略.env或者node_modules&#xff0c;导致后面将.env加入.gitignore也不生效。 取消文件跟踪&#xff1a;如果是因为 node_modules 已被跟踪导致忽略无效&#xff0c; 可以使用命令git rm -r --cached node_modules来删除缓存&…

开讲啦|MBSE公开课:第五集 MBSE中期设想(下)

第五集 在本集课程中&#xff0c;刘玉生教授以MBSE建模工具选型及二次定制开发为核心切入点&#xff0c;系统阐释了"为何需要定制开发"与"如何实施定制开发"的实践逻辑&#xff0c;并提炼出MBSE中期实施的四大核心要素&#xff1a;高效高质建摸、跨域协同…

CSDN个人博客文章全面优化过程

两天前达到博客专家申请条件&#xff0c;兴高采烈去申请博客专家&#xff1a; 结果今天一看&#xff0c;申请被打回了&#xff1a; 我根据“是Yu欸”大神的博客&#xff1a; 【2024-完整版】python爬虫 批量查询自己所有CSDN文章的质量分&#xff1a;附整个实现流程_抓取csdn的…

Websocket的Key多少个字节

在WebSocket协议中&#xff0c;握手过程中的Sec-WebSocket-Key是一个由客户端生成的随机字符串&#xff0c;用于安全地建立WebSocket连接。这个Sec-WebSocket-Key是基于Base64编码的&#xff0c;并且通常由客户端在WebSocket握手请求的头部字段中发送。根据WebSocket协议规范&a…

SVT-AV1编码器中实现WPP依赖管理核心调度

一 assign_enc_dec_segments 函数。这个函数是 SVT-AV1 编码器中实现波前并行处理&#xff08;WPP&#xff09; 和分段依赖管理的核心调度器之一。//函数功能&#xff1a;分配编码解码段任务//返回值Bool//True 成功分配了一个段给当前线程&#xff0c;调用者应该处理这个段//F…

直接让前端请求代理到自己的本地服务器,告别CV报文到自己的API工具,解放双手

直接使用前端直接调用本地服务器&#xff0c;在自己的浏览器搜索插件proxyVerse&#xff0c;类似的插件应该还有一些&#xff0c;可以选择自己喜欢的这类插件可以将浏览器请求&#xff0c;直接转发到本地服务器&#xff0c;这样在本地调试的时候&#xff0c;不需要前端项目&…

Golang Goroutine 与 Channel:构建高效并发程序的基石

在当今这个多核处理器日益普及的时代&#xff0c;利用并发来提升程序的性能和响应能力已经成为软件开发的必然趋势。而Go语言&#xff0c;作为一门为并发而生的语言&#xff0c;其设计哲学中将“并发”置于核心地位。其中&#xff0c;Goroutines 和 Channels 是Go实现并发编程的…