#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
Я работаю над проектом для новорожденных, суть которого заключается в том, что новорожденным присваивается определенный балл в зависимости от симптомов, которые у них есть в данный момент времени. Основываясь на том, как их оценки меняются со временем, мы решаем, увеличивать ли дозировки лекарств, сохранять их прежними или отучить их. Мы обозначаем эти 3 состояния численно как 1 (увеличение), 0 (поддержание) или -1 (отлучение от груди), так что каждый момент времени имеет соответствующую оценку. Правила, позволяющие решить, что делать, следующие:
- Увеличьте дозировку, если сумма 3 последовательных баллов> = 24 ИЛИ один балл > = 12 ( 1).
- Более низкая доза если прошло по крайней мере 48 часов без необходимости увеличения дозы, сумма 3 самых последних оценок равна <18, И ни одна оценка не превышает 8 (-1).
- В противном случае поддерживайте дозу (0)
Пример кода таков:
import pandas as pd
df = pd.DataFrame({
'baby': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B','B', 'B', 'B', 'B', 'B','B','B'],
'dateandtime': ['7/20/2009 5:00:00 PM', '7/18/2009 5:00:00 PM', '7/18/2009 7:00:00 PM', '7/17/2009 6:00:00 AM','7/17/2009 12:01:00 AM', '7/14/2009 12:01:00 AM', '7/19/2009 5:00:00 AM', '7/16/2009 9:00:00 PM','7/19/2009 9:00:00 AM', '7/14/2009 6:00:00 PM', '7/15/2009 3:04:00 PM', '7/20/2009 5:00:00 PM','7/16/2009 12:01:00 AM', '7/18/2009 1:00:00 PM', '7/16/2009 6:00:00 AM', '7/13/2009 9:00:00 PM','7/19/2009 1:00:00 AM','7/15/2009 12:04:00 AM'],
'score': [6, 3, 7, 5, 13, 14, 5, 4, 11, 4, 4, 6, 7, 4, 6, 12, 6, 6],
})
df.dateandtime = pd.to_datetime(df['dateandtime']) # change column type for ease of indexing
df = df.set_index('dateandtime')
df.sort_index(inplace = True)
df = df[~df.index.duplicated()] #Remove any duplicated rows
#Calculate conditions
df['sum_3_scores'] = df.groupby('baby')['score'].rolling(3).sum().reset_index(0,drop=True)
df['max_1_score'] = df.groupby('baby')['score'].rolling(1).max().reset_index(0,drop=True)
df['sum_3_scores_48hours'] = df.groupby('baby')['score'].rolling('48h', max_periods=3).apply(lambda x: sum(x[-3:])).reset_index(0,drop=True)
#scoring logic
def score(data):
if data['sum_3_scores'] >= 24 or data['max_1_score'] >= 12:
return 1
if data['sum_3_scores_48hours'] < 18 and data['max_1_score'] < 8 and data['sum_3_scores']<24:
return -1
return 0
df['rule (original)'] = df.apply(score, axis = 1)
#just for a nicely ordered output
df.reset_index().set_index(['baby','dateandtime']).sort_index()
df.sort_values(by=['baby', 'dateandtime'],inplace=True)
df.drop(['sum_3_scores','sum_3_scores_48hours'], axis=1, inplace=True)
df.sort_values(by=['baby', 'dateandtime'],inplace=True)
print(df)
Это дает хороший результат, к которому я стремлюсь:
baby score max_1_score rule (original)
dateandtime
2009-07-14 00:01:00 A 14 14.0 1
2009-07-16 21:00:00 A 4 4.0 0
2009-07-17 00:01:00 A 13 13.0 1
2009-07-17 06:00:00 A 5 5.0 0
2009-07-18 17:00:00 A 3 3.0 0
2009-07-18 19:00:00 A 7 7.0 -1
2009-07-19 05:00:00 A 5 5.0 -1
2009-07-19 09:00:00 A 11 11.0 0
2009-07-13 21:00:00 B 12 12.0 1
2009-07-14 18:00:00 B 4 4.0 0
2009-07-15 00:04:00 B 6 6.0 0
2009-07-15 15:04:00 B 4 4.0 -1
2009-07-16 00:01:00 B 7 7.0 -1
2009-07-16 06:00:00 B 6 6.0 -1
2009-07-18 13:00:00 B 4 4.0 -1
2009-07-19 01:00:00 B 6 6.0 -1
2009-07-20 17:00:00 B 6 6.0 -1
Все делает то, что я хочу, за исключением того, что проблема здесь в том, что это не соответствует части правила уменьшения дозы, которая гласит: «Уменьшите дозу, если есть по крайней мере 48 часов без необходимости увеличения дозы». (другими словами, если есть 1, я не могу получить -1по крайней мере, до 48 часов спустя). Например, я увеличил дозировку в «2009-07-17 00: 01:00», но затем код говорит снизить дозу в «2009-07-18 19:00:00», что составляет менее 48 часов. Поэтому я знаю, что проблема в моей функции «оценка def (данные)», но я не уверен, как изменить эту функцию, чтобы она знала, что не выдает -1, если временные точки находятся менее чем в 48 часах от увеличенной дозы.
Ответ №1:
Ниже будет указано количество дней:
import pandas as pd
df = pd.DataFrame(
{
'baby': [
'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B','B', 'B', 'B', 'B', 'B','B','B'
],
'dateandtime': [
'7/20/2009 5:00:00 PM', '7/18/2009 5:00:00 PM', '7/18/2009 7:00:00 PM', '7/17/2009 6:00:00 AM',
'7/17/2009 12:01:00 AM', '7/14/2009 12:01:00 AM', '7/19/2009 5:00:00 AM', '7/16/2009 9:00:00 PM',
'7/19/2009 9:00:00 AM', '7/14/2009 6:00:00 PM', '7/15/2009 3:04:00 PM', '7/20/2009 5:00:00 PM',
'7/16/2009 12:01:00 AM', '7/18/2009 1:00:00 PM', '7/16/2009 6:00:00 AM', '7/13/2009 9:00:00 PM',
'7/19/2009 1:00:00 AM','7/15/2009 12:04:00 AM'
],
'score': [
6, 3, 7, 5, 13, 14, 5, 4, 11, 4, 4, 6, 7, 4, 6, 12, 6, 6
]
}
)
df["dateandtime"] = pd.to_datetime(df['dateandtime'])
df = df.set_index('dateandtime').sort_index()
df = df[~df.index.duplicated()]
ndays = (
df.assign(days=0)
.groupby("baby")["days"].rolling(3)
.apply(lambda row: (row.index.max() - row.index.min()).days)
)
df = df.reset_index().merge(ndays, on=["dateandtime", "baby"]).set_index("dateandtime")
Затем вы можете рассчитать оценку на основе этого нового столбца
Комментарии:
1. Возможно, я сделал что-то не так, но это дает мне: AttributeError: объект ‘numpy.ndarray’ не имеет атрибута ‘index’
2. Для завершения я включил часть вашего кода в свой ответ. Он работает без ошибок для моей версии pandas (1.0.5). У вас все еще есть эта ошибка с обновленным фрагментом?