欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

医学预后的深度学习--第2课第3周大作业--淋巴瘤患者生存分析实战:使用卡普兰-梅耶法进行数据分析

最编程 2024-06-16 12:27:43
...


欢迎来到课程二的第三个作业。在这个作业中,我们将使用Python来构建一些统计模型,这些模型是我们上周学到的,用于分析淋巴瘤患者数据集的生存估计。我们还将评估这些模型并解释它们的输出。在此过程中,您将学习以下内容:

  • Censored(删失) Data
  • Kaplan-Meier Estimates
  • Subgroup Analysis

作业解析

作业名:
Survival Estimates that Vary with Time.ipynb

作业地址:
github --> bharathikannann/AI-for-Medicine-Specialization-deeplearning.ai --> AI for Medical Prognosis --> Week 3

导入包

import lifelines
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from util import load_data

from lifelines import KaplanMeierFitter as KM
from lifelines.statistics import logrank_test
  1. lifelines是一个开源的数据分析库,主要用于生存分析和可靠性分析。它提供了一些常见的生存分析工具,如Kaplan-Meier曲线、Cox比例风险模型等,方便用户进行生存数据的处理和分析。
  2. numpy是Python科学计算中的基础包,提供了支持多维数组和矩阵运算的工具,是众多科学计算和数据分析库的基础
  3. pandas是Python数据分析的核心库之一,主要用于数据清洗、处理、转换和分析。
  4. matplotlib是Python中最流行的绘图库之一。

加载数据集

该实验用的数据集是 lifelines 提供的淋巴瘤数据

data = load_data()
print("data shape: {}".format(data.shape))
data.head()

深度学习用于医学预后-第二课第三周大作业-淋巴瘤患者生存分析实战:使用 Kaplan-Meier 方法进行数据分析_数据分析


"Time”一栏列出了病人在死亡或删失前活了多久。

"Event"栏显示是否观察到死亡。如果观察到事件(即患者死亡),则事件为1,如果数据删失,则事件为0。

这里的删失意味着没有任何观察到的事件就结束了。例如,让病人最多住院100天。如果患者在44天后死亡,其事件记录为Time = 44, event = 1。如果患者在100天后出院,3天后死亡(共103天),则在我们的流程中没有观察到该事件,对应的行Time = 100, event = 0。如果病人在入院后存活了25年,他们的数据仍然是Time = 100, Event = 0。

删失数据

我们可以绘制一个生存时间的直方图,看看在删失或事件发生之前,案例存活了多长时间。

深度学习用于医学预后-第二课第三周大作业-淋巴瘤患者生存分析实战:使用 Kaplan-Meier 方法进行数据分析_深度学习_02

练习1

编写一个计算删失数据比例的函数

def frac_censored(df):
    """
    Return percent of observations which were censored.
    
    Args:
        df (dataframe): dataframe which contains column 'Event' which is 
                        1 if an event occurred (death)
                        0 if the event did not occur (censored)
    Returns:
        frac_censored (float): fraction of cases which were censored. 
    """
    result = 0.0
    
    ### START CODE HERE ###
    result =len(df[df["Event"]==0]["Event"])/len(df)
    
    ### END CODE HERE ###
    
    return result

深度学习用于医学预后-第二课第三周大作业-淋巴瘤患者生存分析实战:使用 Kaplan-Meier 方法进行数据分析_数据集_03

生存估计

为了说明Kaplan Meier方法的优点,我们将从一个简单的估计器开始,用于估计上述生存函数。为了估计这个量,我们将计算时间 t 之后仍然存活的人数除以在时间 t 之前未删失的人数。

用公式表示为:

,
.

的计算,需要注意的是,在t时间内删失的人(ei=0 且 Time < t)是不包括在内的,因为不知道它具体生存情况. 这里 的计算中, e_i = 1 包含两种情况,一种是在 t 时间前死的,一种是 t 时间后死的。而 T_i > t 也包含两种情况,一种是 t 时间后删失,一种是 t 时间后死亡。 显然二者是有重叠的,但是把它们合并在一起(逻辑: or),就可以得到在 t 时间内没有删失的总人数。

有点绕,自己捋捋~~

理解到了,看代码就很简单了

简单估计函数

def naive_estimator(t, df):
    """
    Return naive estimate for S(t), the probability
    of surviving past time t. Given by number
    of cases who survived past time t divided by the
    number of cases who weren't censored before time t.
    
    Args:
        t (int): query time
        df (dataframe): survival data. Has a Time column,
                        which says how long until that case
                        experienced an event or was censored,
                        and an Event column, which is 1 if an event
                        was observed and 0 otherwise.
    Returns:
        S_t (float): estimator for survival function evaluated at t.
    """
    S_t = 0.0
    
    ### START CODE HERE ###
    X_t = len(df[df["Time"]>t])
    M_t = len(df[(df["Time"]>t) | (df["Event"]==1)])
    S_t = X_t/M_t
    ### END CODE HERE ###
    
    return S_t

我们知道一个 t 怎么求生存率之后,接下来,使用 for 循环求连续 t 的生存率。

深度学习用于医学预后-第二课第三周大作业-淋巴瘤患者生存分析实战:使用 Kaplan-Meier 方法进行数据分析_深度学习_09

Kaplan Meier 估计

接下来我们将其与Kaplan Meier估计进行比较。在下面的单元格中,编写一个函数,计算数据集中每个不同时间 的Kaplan Meier估计。

回想一下Kaplan-Meier估计:

其中 是在数据集中观察到的事件, 是时间 的死亡人数, 是我们知道在时间 之前幸存下来的人数。

# UNQ_C3 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)
def HomemadeKM(df):
    """
    Return KM estimate evaluated at every distinct
    time (event or censored) recorded in the dataset.
    Event times and probabilities should begin with
    time 0 and probability 1.
    
    Example:
    
    input: 
    
         Time  Censor
    0     5       0
    1    10       1
    2    15       0
    
    correct output: 
    
    event_times: [0, 5, 10, 15]
    S: [1.0, 1.0, 0.5, 0.5]
    
    Args:
        df (dataframe): dataframe which has columns for Time
                          and Event, defined as usual.
                          
    Returns:
        event_times (list of ints): array of unique event times
                                      (begins with 0).
        S (list of floats): array of survival probabilites, so that
                            S[i] = P(T > event_times[i]). This 
                            begins with 1.0 (since no one dies at time
                            0).
    """
    # individuals are considered to have survival probability 1
    # at time 0
    event_times = [0]
    p = 1.0
    S = [p]
    
    ### START CODE HERE (REPLACE INSTANCES OF 'None' with your code) ###
    
    # get collection of unique observed event times
    observed_event_times = df["Time"].unique()
  
    # sort event times
    observed_event_times = sorted(observed_event_times)
    
    # iterate through event times
    for t in observed_event_times:
  
        # compute n_t, number of people who survive to time t
        n_t = len(df[df["Time"]>=t])
  
        # compute d_t, number of people who die at time t
        d_t = len(df[(df["Time"]==t) & (df["Event"]==1)])
        
        # update p
        p = p * (1 - (d_t/n_t))
        S.append(p)
        event_times.append(t)
  
        # update S and event_times (ADD code below)
        # hint: use append
        
    
    ### END CODE HERE ###
  
    return event_times, S

深度学习用于医学预后-第二课第三周大作业-淋巴瘤患者生存分析实战:使用 Kaplan-Meier 方法进行数据分析_Time_17

子组分析

我们可以看到在时间和删失信息的列之外,数据集中还有一个名为Stage_group的列。

这个列中的数值1代表患有III期癌症的患者,2代表IV期。我们想比较这两组患者的生存函数。

这一次,我们将使用lifelines中的KaplanMeierFitter类。运行下面的代码块来拟合并绘制每组的Kaplan Meier曲线。

S1 = data[data.Stage_group == 1]
km1 = KM()
km1.fit(S1.loc[:, 'Time'], event_observed = S1.loc[:, 'Event'], label = 'Stage III')

S2 = data[data.Stage_group == 2]
km2 = KM()
km2.fit(S2.loc[:, "Time"], event_observed = S2.loc[:, 'Event'], label = 'Stage IV')

ax = km1.plot(ci_show=False)
km2.plot(ax = ax, ci_show=False)
plt.xlabel('time')
plt.ylabel('Survival probability estimate')
plt.savefig('two_km_curves', dpi=300)

深度学习用于医学预后-第二课第三周大作业-淋巴瘤患者生存分析实战:使用 Kaplan-Meier 方法进行数据分析_深度学习_18

注意: 对 KaplanMeierFitter 的使用不熟悉的,可以查看下面这篇
生存分析利器:Python 中的 Kaplan-Meier Fitter 类详解

比较一下两个组中,在相同时间的生存率有什么不同

survivals = pd.DataFrame([90, 180, 270,