代码之家  ›  专栏  ›  技术社区  ›  Giannis

绘图图表上的次/平行X轴(Python)

  •  0
  • Giannis  · 技术社区  · 7 年前

    我需要渲染 at_risk 卡普兰迈尔图上的数字。

    最终结果应与此类似:

    enter image description here

    我在渲染时遇到的问题是 No. of patients at risk 在图的底部。此处显示的值与X轴上的值相对应。所以本质上,它就像一个平行于x的y轴。

    我一直在尝试复制这里发现的多个轴( https://plot.ly/python/multiple-axes/ )没有成功,也尝试了有一个子块并隐藏除x轴以外的所有内容,但是它的值与上面的图形不一致。

    最好的方法是什么?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Maximilian Peters    7 年前

    你可以绘制卡普兰-迈耶生存图,通过使用子图绘制有风险的患者。第一个图有存活率,第二个图是散点图,只显示文本,即不显示标记。

    两个图都有相同的y轴,处于危险中的患者在各自的x值上绘制。

    更多示例如下: https://github.com/Ashafix/Kaplan-Meier_Plotly

    例1-女性和男性患者的肺癌

    import pandas as pd
    import lifelines
    import plotly
    import numpy as np
    plotly.offline.init_notebook_mode()
    
    df = pd.read_csv('http://www-eio.upc.edu/~pau/cms/rdata/csv/survival/lung.csv')
    
    fig = plotly.tools.make_subplots(rows=2, cols=1, print_grid=False)
    kmfs = []
    
    dict_sex = {1: 'Male', 2: 'Female'}
    
    steps = 5 # the number of time points where number of patients at risk which should be shown
    
    x_min = 0 # min value in x-axis, used to make sure that both plots have the same range
    x_max = 0 # max value in x-axis
    
    for sex in df.sex.unique():
        T = df[df.sex == sex]["time"]
        E = df[df.sex == sex]["status"]
        kmf = lifelines.KaplanMeierFitter()
    
        kmf.fit(T, event_observed=E)
        kmfs.append(kmf)
        x_max = max(x_max, max(kmf.event_table.index))
        x_min = min(x_min, min(kmf.event_table.index))
        fig.append_trace(plotly.graph_objs.Scatter(x=kmf.survival_function_.index,
                                                   y=kmf.survival_function_.values.flatten(),  
                                                   name=dict_sex[sex]), 
                         1, 1)
    
    
    for s, sex in enumerate(df.sex.unique()):
        x = []
        kmf = kmfs[s].event_table
        for i in range(0, int(x_max), int(x_max / (steps - 1))):
            x.append(kmf.iloc[np.abs(kmf.index - i).argsort()[0]].name)
        fig.append_trace(plotly.graph_objs.Scatter(x=x, 
                                                   y=[dict_sex[sex]] * len(x), 
                                                   text=[kmfs[s].event_table[kmfs[s].event_table.index == t].at_risk.values[0] for t in x], 
                                                   mode='text', 
                                                   showlegend=False), 
                         2, 1)
    
    # just a dummy line used as a spacer/header
    t = [''] * len(x)
    t[1] = 'Patients at risk'
    fig.append_trace(plotly.graph_objs.Scatter(x=x, 
                                               y=[''] * len(x), 
                                               text=t,
                                               mode='text', 
                                               showlegend=False), 
                     2, 1)
    
    
    # prettier layout
    x_axis_range = [x_min - x_max * 0.05, x_max * 1.05]
    fig['layout']['xaxis2']['visible'] = False
    fig['layout']['xaxis2']['range'] = x_axis_range
    fig['layout']['xaxis']['range'] = x_axis_range
    fig['layout']['yaxis']['domain'] = [0.4, 1]
    fig['layout']['yaxis2']['domain'] = [0.0, 0.3]
    fig['layout']['yaxis2']['showgrid'] = False
    fig['layout']['yaxis']['showgrid'] = False
    
    plotly.offline.iplot(fig)
    

    enter image description here 例2-不同治疗的结肠癌

    df = pd.read_csv('http://www-eio.upc.edu/~pau/cms/rdata/csv/survival/colon.csv')
    
    fig = plotly.tools.make_subplots(rows=2, cols=1, print_grid=False)
    kmfs = []
    
    steps = 5 # the number of time points where number of patients at risk which should be shown
    
    x_min = 0 # min value in x-axis, used to make sure that both plots have the same range
    x_max = 0 # max value in x-axis
    
    for rx in df.rx.unique():
        T = df[df.rx == rx]["time"]
        E = df[df.rx == rx]["status"]
        kmf = lifelines.KaplanMeierFitter()
    
        kmf.fit(T, event_observed=E)
        kmfs.append(kmf)
        x_max = max(x_max, max(kmf.event_table.index))
        x_min = min(x_min, min(kmf.event_table.index))
        fig.append_trace(plotly.graph_objs.Scatter(x=kmf.survival_function_.index,
                                                   y=kmf.survival_function_.values.flatten(),
                                                   name=rx), 
                         1, 1)
    
    
    fig_patients = []
    for s, rx in enumerate(df.rx.unique()):
        kmf = kmfs[s].event_table
        x = []
        for i in range(0, int(x_max), int(x_max / (steps - 1))):
            x.append(kmf.iloc[np.abs(kmf.index - i).argsort()[0]].name)
        fig.append_trace(plotly.graph_objs.Scatter(x=x, 
                                                   y=[rx] * len(x), 
                                                   text=[kmfs[s].event_table[kmfs[s].event_table.index == t].at_risk.values[0] for t in x], 
                                                   mode='text', 
                                                   showlegend=False), 
                         2, 1)
    
    # just a dummy line used as a spacer/header
    t = [''] * len(x)
    t[1] = 'Patients at risk'
    fig.append_trace(plotly.graph_objs.Scatter(x=x, 
                                               y=[''] * len(x), 
                                               text=t,
                                               mode='text', 
                                               showlegend=False), 
                     2, 1)
    
    
    # prettier layout
    x_axis_range = [x_min - x_max * 0.05, x_max * 1.05]
    fig['layout']['xaxis2']['visible'] = False
    fig['layout']['xaxis2']['range'] = x_axis_range
    fig['layout']['xaxis']['range'] = x_axis_range
    fig['layout']['yaxis']['domain'] = [0.4, 1]
    fig['layout']['yaxis2']['domain'] = [0.0, 0.3]
    fig['layout']['yaxis2']['showgrid'] = False
    fig['layout']['yaxis']['showgrid'] = False
    
    plotly.offline.iplot(fig)
    

    enter image description here

        2
  •  -1
  •   Cam.Davidson.Pilon    7 年前

    这也是生命线的一部分:

    from lifelines import KaplanMeierFitter
    
    ix = waltons['group'] == 'control'
    
    ax = plt.subplot(111)
    
    kmf_control = KaplanMeierFitter()
    ax = kmf_control.fit(waltons.loc[ix]['T'], waltons.loc[ix]['E'], label='control').plot(ax=ax)
    
    kmf_exp = KaplanMeierFitter()
    ax = kmf_exp.fit(waltons.loc[~ix]['T'], waltons.loc[~ix]['E'], label='exp').plot(ax=ax)
    
    
    from lifelines.plotting import add_at_risk_counts
    add_at_risk_counts(kmf_exp, kmf_control, ax=ax)
    

    https://lifelines.readthedocs.io/en/latest/Examples.html#displaying-multiple-at-risk-counts-below-plots

    不过,我不确定这是否能很好地与阴谋