🏥

NHANES 数据分析教程

美国营养健康调查(National Health and Nutrition Examination Survey)

NHANES 概述

NHANES 由美国 CDC 主持的大型横断面调查,包含体检、实验室检查和问卷数据。 clinResearchKit 封装了从数据加载、权重处理到回归分析的全流程。

适用场景

横断面研究、巢式病例对照、流行病学关联分析

核心优势

自动处理复杂调查权重(PCM, WTMEC4YR, SDMVPSU 等)

01 离线数据库标准化(推荐)

如果你的 NHANES 离线库同时包含原始 XPT、官方文档以及 1988–2018 harmonized 表,建议先使用 nhanes_build_standardized() 建立一个非破坏式标准化入口层。该流程会在 NHANES 根目录下生成 nhanes_standardized/,自动整理 README、manifest、逐表 RDS 与兼容 .RData,后续读取时不需要反复手动指定复杂路径。

library(clinResearchKit)

# 首次配置或换设备时,先设置 NHANES 根目录
locate_data("nhanes", "/Users/angus/Documents/02_已完成项目/NHANES离线数据库")

# 构建非破坏式标准化入口层
nhanes_build_standardized()

# 查看逻辑数据集索引
idx <- nhanes_read_standardized("dataset_index")

# 查看 harmonized clean 清单(不全部载入内存)
clean_manifest <- nhanes_read_standardized("harmonized_clean", load = FALSE)

# 按需读取指定表
demo <- nhanes_read_standardized("harmonized_clean", tables = "demographics_clean")

推荐读取顺序:dataset_index 适合快速查看本地表与官方 NHANES 链接映射; harmonized_clean 适合按需提取 clean 大表; inventory 会盘点全库文件,包括被标记为排除的噪声目录,因此更适合审计而不是直接分析。

标准化产物:会自动生成总 README、manifest/index、逐表 .rds 与兼容 .RData 的打包入口。

跨设备迁移:最稳的方式是整个 NHANES 根目录一起迁移到新机器。迁移后重新执行:

locate_data("nhanes", "新设备上的 NHANES 根目录")
nhanes_build_standardized()

02 数据加载与合并

原始 NHANES 离线库支持两种读取方式:一类是直接使用 DEMOBMX 这类逻辑数据代码, 自动汇总当前根目录下的所有匹配周期;另一类是使用 DEMO_BBMX_B 这类带后缀的 dataset stem, 精确锁定单个调查周期。

# 加载包
library(clinResearchKit)

# 方式 A:bare dataset code,会自动匹配 NHANES 根目录下所有对应周期
data <- nhanes_merge(c(
  "DEMO",   # 人口学数据
  "BMX",    # 体格测量(BMI、血压等)
  "BPX"     # 血压检查
))

# 方式 B:带后缀 dataset stem,只读取单个周期
# 下面用 B (= 2001-2002) 举例;实际使用时请替换成你本地存在的周期后缀
data_single_cycle <- nhanes_merge(c(
  "DEMO_B",
  "BMX_B",
  "BPX_B"
))

# 单表读取时,无扩展名 stem 也可以直接识别
demo_b <- nhanes_load("DEMO_B")

# 根据分析变量自动推荐权重,再生成多周期权重
wt_var <- nhanes_select_weight(data, c("BMXBMI", "BPXSY1"))
data <- nhanes_weight_multi_cycle(data, weight_var = wt_var)

说明:DEMO / BMX 这类 bare dataset code 会自动展开为当前 NHANES 根目录下的全部匹配周期; DEMO_B / BMX_B 这类 stem 则固定到单个调查周期。

提示:如果你已经完成 nhanes_build_standardized(), 推荐优先使用 nhanes_read_standardized() 读取整理后的 clean 表;原始逐表合并更适合需要保留官方原始文件结构时使用。

注意:nhanes_select_weight() 用来选择合适的权重变量,不用于按年份筛选调查周期;如需锁定单周期,请直接改用 DEMO_BBMX_B 这类带后缀 stem, 并把 _B 替换成你本地实际存在的后缀。

03 Table 1(三线表)

# 生成 Table 1(按糖尿病状态分层)
tbl <- nhanes_table1(
  data,
  strata      = "DIABETES",    # 分层变量
  cat_vars    = c("sex", "race", "smoke"),
  cont_vars    = c("age", "BMI", "SBP", "LDL"),
  test         = TRUE,             # 自动进行组间比较检验
  export       = "xlsx",         # 导出为 Excel
  filename     = "table1.xlsx"
)

# 打印查看
print(tbl)

Table 1 解读:连续变量显示为均值±标准差或中位数(IQR),分类变量显示为 n (%), 自动进行 t 检验/卡方检验,并标注 P 值。

04 创建调查设计对象

NHANES 使用复杂抽样设计,必须创建调查设计对象后才能进行加权回归分析。

# 创建调查设计对象(自动识别所有调查周期)
design <- create_nhanes_design(nhanes_data)

# 指定单个调查周期
design <- create_nhanes_design(data_2017)

# 自定义权重变量(高级)
design <- create_nhanes_design(
  nhanes_data,
  weight_var   = "WTMEC4YR",
  cluster_var  = "SDMVPSU",
  strata_var   = "SDMVSTRA"
)

注意:所有后续的回归分析函数(nhanes_coxnhanes_logistic) 都会自动使用这个调查设计,不需要重复传入。

05 Cox 比例风险模型

# Cox 回归(结局:全因死亡)
result <- nhanes_cox(
  data,
  formula = Surv(permth_int/12, mortstat) ~ BMI_group + age + sex + race,
  time_unit = "month"
)

# 查看结果
print(result)
summary(result)

# 提取 HR 及置信区间
print_summary(result)
# 逻辑回归
lr_result <- nhanes_logistic(
  data,
  formula = DIABETES ~ BMI + age + sex + race,
  exponentiate = TRUE
)

# 批量逻辑回归(多个自变量)
batch <- nhanes_batch_glm(
  data,
  y_var       = "DIABETES",
  x_vars       = c("BMI", "SBP", "LDL", "CRP"),
  family       = "binomial",
  adjust_vars  = c("age", "sex", "race")
)

06 森林图

# Cox 回归森林图
p <- nhanes_forest_plot(result, title = "BMI 与全因死亡(NHANES 2017-2018)")
print(p)
ggsave("forest_cox.pdf", p, width = 8, height = 6)

# 逻辑回归森林图
p_lr <- nhanes_forest_plot(lr_result, title = "代谢指标与糖尿病")
ggsave("forest_logistic.pdf", p_lr, width = 8, height = 6)

森林图自定义:支持修改配色(colors)、 字体大小(base_size)、 参考线(ref_line)等参数。

07 限制性立方样条(RCS)非线性分析

检验自变量与结局是否存在非线性关系,自动选择最优 knots 数量。

# RCS 非线性分析(BMI 与高血压)
rcs_result <- nhanes_rcs(
  data,
  x_var    = "BMXBMI",       # 连续自变量
  y_var    = "hypertension",  # 二分类结局
  knots    = 3,              # 节点数(3 或 4 常用)
  adjust   = c("age", "sex", "race")
)

# 非线性检验 P 值
print(rcs_result$p_nonlinear)

# 绘制 RCS 曲线
ggplot(rcs_result$rcs_data,
       aes(x = BMXBMI, y = OR)) +
  geom_line() +
  geom_ribbon(aes(ymin = lower, ymax = upper), alpha = 0.2) +
  geom_hline(yintercept = 1, linetype = "dashed", color = "red") +
  labs(x = "BMI (kg/m²)", y = "OR")