Вы можете построить графики выживаемости Каплана-Мейера для пациентов с риском с помощью Plotly, используя подзаговоры. Первый график имеет коэффициент выживаемости, второй график представляет собой точечный график, на котором показан только текст, то есть маркеры не показаны.
Оба графика имеют одинаковую ось Y, и пациенты в группе риска представлены с соответствующими значениями X.
Больше примеров здесь: https://github.com/Ashafix/Kaplan-Meier_Plotly
Пример 1 - Рак легких у женщин и мужчин [ 1110]
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)
Пример 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)
Почему беспокойство с несмещением, когда выражение else должно всегда происходить?
for apple in tree:
if (apple.weight + basket.weight) > 10:
send(basket)
basket.clear()
basket.add(apple)
Так или иначе я вполне уверен, что Python не имеет вида поведения, которое Вы ищете.
Я изучаю Python, и у меня есть ситуация, где я хочу использовать объекты от итератора. Хитрая часть что происходит в определенных условиях, я хочу "не выполнить итерации". Таким образом, отложите объект на переднюю сторону итератора, прежде чем я циклично выполнюсь.
Вот простое решение:
class MyIterator(object): # undo-able iterator wrapper
def __init__(self, iterable):
super(MyIterator, self).__init__()
self.iterator = iter(iterable)
self.stack = []
def __iter__(self):
return self
def next(self):
if self.stack:
return self.stack.pop()
return self.iterator.next() # Raises StopIteration eventually
def undo(self, item):
self.stack.append(item)
for i in MyIterator(xrange(5)): print i
0
1
2
3
4
rng = MyIterator(xrange(5))
rng.next()
0
rng.next()
1
rng.undo(1)
rng.next()
1
Я сказал бы, что большей частью решения Pythonic является самое простое. Вместо того, чтобы пытаться перенести итератор в выражение генератора, которое позволяет Вам "отслеживать в обратном порядке" или что-то столь же сложное, используйте некоторое время цикл, как Вы имеете в Perl! Итераторы не смешиваются очень приятно с мутацией, anywho.
Простой перевод Вашей реализации (игнорирующий оптимизацию @Patrick):
while tree:
apple = tree.pop(0)
if apple.weight + basket.weight > 10:
basket.send()
basket.clear()
tree.insert(0, apple) # Put it back.
else:
basket.append(apple)
Или, Вы могли использовать a peek
- как функциональность с заказанными индексами последовательности:
while tree:
apple = tree[0] # Take a peek at it.
if apple.weight + basket.weight > 10:
basket.send()
basket.clear()
else:
basket.append(tree.pop(0))
Если Вам не нравится "простой" аргумент, проверьте collections.deque
итераторы упоминаются в вышеупомянутом (связанном) потоке.
Если Вы не хотите следовать за предложением других просто удаления выражения else, можно записать собственное unshift
функция, которая будет работать в некотором роде подобная perl's с любым повторяемым:
class UnshiftableIterable(object):
def __init__(self, iterable):
self._iter = iter(iterable)
self._unshifted = [] # empty list of unshifted stuff
def __iter__(self):
while True:
if self._unshifted:
yield self._unshifted.pop()
else:
yield self._iter.next()
def unshift(self, item):
self._unshifted.append(item)
Затем в Вашем коде:
it = UnshiftableIterable(tree)
for apple in tree:
if weigth(basket) + weight(apple) > MAX_WEIGHT:
send(basket)
basket = []
it.unshift(apple)
else:
basket.append(apple)
Некоторое тестирование UnshiftableIterable
:
it = UnshiftableIterable(xrange(5))
for i in it:
print '*',
if i == 2:
it.unshift(10)
else:
print i,
# output: * 0 * 1 * * 10 * 3 * 4
Нет никакого пути общего способа продвинуть значение в итератор в Python. Стек или связанный список лучше подходят для этого.
Если Вы выполняете итерации по списку или чему-то, конечно, можно добавить объект вручную назад к списку. Но можно также выполнить итерации по объектам, которыми нельзя управлять таким способом.
Если Вы хотите использовать Python для реализации того алгоритма, необходимо будет выбрать структуру данных, которая позволяет операции, которые Вы хотите использовать. Я предлагаю .push()
и .pop()
методы, которые позволяют Вам рассматривать списки как стеки.
Вы ищете генератор, итератор, который может получить модификации к его внутреннему состоянию через отправление () метод
https://docs.python.org/howto/functional.html#passing-values-into-a-generator
В то время как я писал, что этот @Patrick уже предложил то же самое. Но так как я записал это, я вставлю код так или иначе с комментариями в методах выделения кода от Patrick.
import random
apples=[random.randint(1,3) for j in range(10)]
print 'apples',apples
basket=[]
y=6
baskets=[]
for i in range(len(apples)):
if sum(basket+[apples[i]])>y:
#basket is full
baskets.append(basket)#basket.send()
basket=[]#basket.empty()
basket.append(apples[i])#add apple to basket
print 'baskets',baskets
хотя это не выталкивает () яблоки от исходного итератора. Отметьте, является ли это желаемым поведением также.
вывод
apples [1, 1, 3, 3, 1, 1, 3, 3, 2, 3]
baskets [[1, 1, 3], [3, 1, 1], [3, 3]]