简体   繁体   English

绘图图上的辅助/平行X轴(python)

[英]Secondary / Parallel X-Axis on Plotly charts (python)

I need to render at_risk numbers on a Kaplan Meier graph. 我需要在Kaplan Meier图上绘制at_risk数字。

The end result should be similar to this: 最终结果应与此类似:

在此处输入图片说明

The bit I am having trouble rendering is the No. of patients at risk at the bottom of the graph. 我在渲染时遇到的困难是图表底部No. of patients at risk中的No. of patients at risk人数。 The values displayed there, correspond to the values on the x-axis. 在那里显示的值对应于x轴上的值。 So in essence, it's like a Y-axis rendered in parallel with the X. 因此,从本质上讲,它就像与X平行绘制的Y轴。

I have been trying to replicate multiple-axis found here ( https://plot.ly/python/multiple-axes/ ) without success, and also tried having a subplot and hide everything but the X-axis, but then its values do not align with the graph above. 我一直在尝试复制在这里找到的多轴( https://plot.ly/python/multiple-axes/ )并没有成功,并且还尝试了一个子图并隐藏除X轴以外的所有内容,但随后它的值可以了与上图不符。

What is the best approach for this? 最好的方法是什么?

You could plot Kaplan-Meier survival graphs with patients at risk with Plotly by using subplots. 您可以通过使用子图来绘制有Plotly风险患者的Kaplan-Meier生存图。 The first plot has the survival rate, the second plot is a scatter plot where only the text is shown, ie the markers are not shown. 第一个图具有存活率,第二个图是散点图,其中仅显示文本,即未显示标记。

Both plots have the same y-axis and the patients at risk are plotted at the respective x-values. 这两个图都有相同的y轴,并且将处于危险状态的患者分别绘制在x值上。

More examples are here: https://github.com/Ashafix/Kaplan-Meier_Plotly 更多示例在这里: https : //github.com/Ashafix/Kaplan-Meier_Plotly

Example 1 - Lung cancer in female and male patients 实施例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)

在此处输入图片说明 Example 2 - Colon cancer with different treatments 实施例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)

在此处输入图片说明

This is builtin to lifelines as well: 这也是内置在生命线中的:

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 https://lifelines.readthedocs.io/en/latest/Examples.html#displaying-multiple-at-risk-counts-below-plots

However, I'm not sure if this works well with plotly 但是,我不确定这是否可以很好地配合使用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM