欢迎大家关注全网生信学习者系列:
针对某个科学问题,通常会在一段时间内对多个同一研究对象进行多次或重复测量,这类数据一般称为纵向数据。纵向数据具有两个特点,一是研究对象重复;二是观察值可能存在缺失值。上述两个因素导致在探索结果和观测指标相关性分析时,一般线性(linear regression model)或广义线性模型(generalized regression model)以及重复测量方差分析(repeated ANOVA)均不适用。因此,广义估计方程(generalized estimating equations,GEE) 和混合线性模型(mixed linear model,MLM) 被广泛应用于纵向数据的统计分析。
上述两种方法适合解析因变量和自变量的相关性
基本概念
假定因变量y,自变量X,作为固定变量,而Z则是随机变量(协变量)。
$$y = X\beta + Z\mu + \epsilon $$
回归系数的95% 置信区间计算:$$CI{0.95}^{\beta{i}} = [\beta{i} - 1.96 * SE(\beta{i}),\space \beta{i} + 1.96 * SE(\beta{i})]$$
为各个变量之间存在不同的单位也即是量纲可能不同,所以对数据做归一化和标准化处理是必须的。
knitr::opts_chunk$set(message = FALSE, warning = FALSE)
library(tidyverse)
library(data.table)
# rm(list = ls())
options(stringsAsFactors = F)
options(future.globals.maxSize = 1000 * 1024^2)
数据来自于一个肾脏病的研究,大家通过以下链接下载:
本案例数据来源于一个肾脏病的研究。研究对200个肾病患者进行随访,每年化验一次肾小球滤过率(GFR,评价肾脏功能的指标,会逐年下降)。主要分析目的是探索基线的尿蛋白定量对GFR年下降率(斜率)的影响(尿蛋白量越大,对肾功能危害越大),混杂因素包括基线年龄和性别。
dataset <- data.table::fread("data_dropout.csv")
dataset <- dataset |>
dplyr::select(-all_of(c("line", "normo")))
head(dataset)
患者GFR是否受到基线年龄、性别、尿蛋白情况以及化验时间影响。另外根据专业医学知识,假设尿蛋白不仅影响GFR的下降率,也影响基线GFR,也即是time和尿蛋白micro和macro存在交互影响(此地排除age,gender对GFR下降率的影响)。
预测变量还需要加上一个时间x尿蛋白的交互项(交互项是指不同的尿蛋白等级会有不同的GFR下降斜率和下降曲线)
summary(dataset)
dataset %>%
group_by(patient) %>%
summarise(
count = n(),
mean = mean(GFR, na.rm=TRUE),
sd = sd(GFR, na.rm=TRUE)
)
ggplot(data = dataset, aes(x = time, y = GFR, group = patient, color = patient)) +
geom_line(alpha = .3) +
labs(title = "GFR Levels of Patient across the therapeutic times") +
theme(legend.position = "none")
rando <- sample(unique(dataset$patient), 10)
indplot <- subset(dataset, patient %in% rando)
ggplot(indplot, aes(x = time, y = GFR)) +
geom_line(color = "tomato") +
facet_wrap( ~ patient) +
labs(x = "time", y="GFR Levels", title="Individual GFR Levels\nfor a Random Sample of Patients") +
theme(axis.text.x=element_blank(), axis.ticks.x=element_blank())
GEE通过协变量patient考虑到他们内部观测值的相关性后再对总体效应进行推断,如何确定分组需要考虑到组群变量。除此之外,确定组内相关关系,还需要考虑到组内观测之间的相关性是相互独立还是相互依赖等各种情况。
library(geepack)
gee_fit <- geeglm(GFR ~ age + gender + micro + macro + time + micro:time + macro:time,
id = patient,
data = dataset,
std.err = "san.se",
corstr = "exchangeable",
family = "gaussian")
gee_fit
GFR ~ age + gender + micro + macro + time + micro:time + macro:time
是因变量和自变量的线性关系方程式,其中micro:time
是交互式影响自变量id = patient
表示每个patients是一个内在cluster的标识,用于剔除内在相关关系std.err = "san.se"
计算评估系数的标准误差,san.se适合cluster数目小于等于30的数据集corstr = "exchangeable"
是构造自变量作业相关矩阵参数
family = "gaussian"
是连接函数,链接因变量和自变量(很多中文教程说是协变量)线性关系的函数提取结果
gee_cc <- coef(summary(gee_fit)) |>
as.data.frame() |>
dplyr::mutate(lower_95CI = round(Estimate - 1.96 * Std.err, 2),
upper_95CI = round(Estimate + 1.96 * Std.err, 2)) |>
dplyr::mutate(Estimate_95CI = paste0(round(Estimate, 2), " (", lower_95CI, ", ", upper_95CI, ")")) |>
dplyr::select(-all_of(c("lower_95CI", "upper_95CI"))) |>
dplyr::mutate(OddRatio = round(exp(Estimate), 2)) |>
dplyr::arrange(`Pr(>|W|)`)
DT::datatable(gee_cc)
在校正年龄和性别下,
library(reticulate)
# myenvs <- conda_list()
#
# envname <- myenvs$name[2]
# use_condaenv(envname, required = TRUE)
# # or
use_condaenv("base", required = TRUE)
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
dataset = pd.read_csv("./InputData/TherapyData/data_dropout.csv")
dataset = dataset.drop(columns = ['line', 'normo'])
dataset.head()
fam = sm.families.Gaussian()
ind = sm.cov_struct.Exchangeable()
mod = smf.gee(formula = "GFR ~ age + gender + micro + macro + time + micro:time + macro:time",
groups = "patient",
data = dataset,
cov_struct = ind,
family = fam)
res = mod.fit()
print(res.summary())
线性混合效应(LME)模型可以被认为是具有附加成分的回归模型,这些成分可以解释个体(重复测量环境)或群体(多层次/分层环境)之间截距和/或斜率参数的变化。区分混合线性模型中的随机效应和固定效应是一个重要的概念。固定效应是具有特定水平的变量,而随机效应捕捉了由于分组或聚类引起的变异性。
比如下方正在探究尿蛋白对来自不同患者的GFR的影响。拥有的变量(例如年龄、性别、尿蛋白等)和患者的变量(patient)。想要了解尿蛋白如何影响患者的G FR。
# 第一种方法
# library(lmerTest)
# mlm_fit <- lmerTest::lmer(GFR ~ age + gender + time + micro + macro +
# micro:time + macro:time +
# (1|patient),
# data = dataset)
# 第二种方法
library(nlme)
mlm_fit <- nlme::lme(GFR ~ age + gender + micro + macro + time + micro:time + macro:time,
random = ~ 1 | patient,
method = "ML",
data = dataset,
control = lmeControl(opt = "optim"))
mlm_fit
构建模型: 通过(1|patient)
确定随机因子
GFR
is the dependent variable you want to model.age
, gender
, time
, micro
, macro
, micro:time
, and macro:time
are the independent variables (fixed effects).(1|patient)
specifies a random intercept
term for the grouping variable patient. This accounts for the fact that measurements are nested within patients, allowing for correlations among measurements within the same patient.summary(mlm_fit)
# mlm_cc <- coef(summary(mlm_fit)) |>
# as.data.frame() |>
# dplyr::mutate(lower_95CI = round(Estimate - 1.96 * `Std. Error`, 2),
# upper_95CI = round(Estimate + 1.96 * `Std. Error`, 2)) |>
# dplyr::mutate(Estimate_95CI = paste0(round(Estimate, 2), " (", lower_95CI, ", ", upper_95CI, ")")) |>
# dplyr::select(-all_of(c("lower_95CI", "upper_95CI"))) |>
# dplyr::mutate(OddRatio = round(exp(Estimate), 2)) |>
# dplyr::arrange(`Pr(>|t|)`)
mlm_cc <- coef(summary(mlm_fit)) |>
as.data.frame() |>
dplyr::mutate(lower_95CI = round(Value - 1.96 * Std.Error, 2),
upper_95CI = round(Value + 1.96 * Std.Error, 2)) |>
dplyr::mutate(Estimate_95CI = paste0(round(Value, 2), " (", lower_95CI, ", ", upper_95CI, ")")) |>
dplyr::select(-all_of(c("lower_95CI", "upper_95CI"))) |>
dplyr::mutate(OddRatio = round(exp(Value), 2)) |>
dplyr::arrange(`p-value`)
DT::datatable(mlm_cc)
综上:GEE和MLM的结果较为接近
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
dataset = pd.read_csv("./InputData/TherapyData/data_dropout.csv")
dataset = dataset.drop(columns = ['line', 'normo'])
dataset.head()
mod_lme = smf.mixedlm(formula = "GFR ~ age + gender + micro + macro + time + micro:time + macro:time",
groups = dataset["patient"],
data = dataset)
modf_lme = mod_lme.fit()
print(modf_lme.summary())
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。