我正在协助一个新生儿项目,该项目主要是研究如何根据一定的分数给予药物剂量。从本质上讲,我得到了一个很大的数据框,其中充满了不同日期和时间点的许多不同婴儿和分数。下面是一个示例:
import numpy as np
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': ['8/2/2009 5:00:00 PM', '7/19/2009 5:00:00 PM', '7/19/2009 1: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, 10, 14, 5, 4, 11, 4, 4, 6, 7, 4, 6, 12, 6, 6]
})
print(df)
我要做的第一件事是使用以下命令按时间顺序排列婴儿和时间戳记(这很重要):
df = df.groupby(['baby', 'dateandtime'])
所以现在我想弄清楚该怎么做的是创建一列添加到我的数据框中,以便在每个时间点,我有-1(减少剂量),0(保持相同剂量)或+1(增加剂量),具体取决于团队根据规则制定的“得分”。我得到的规则如下:如果三个连续得分的总和≥24或最近一个或两个得分的总和≥12,则为+1。如果过去24小时的平均得分小于8,则为-1。分数保持低于8至少48小时后。否则为0。
所以我的问题是:我真的不知道如何编写此规则,特别是因为我不确定如何告诉python“过去48小时内”。我想,如果我知道如何创建一个函数来执行此规则,则可以使用命令df.apply(rule).reset_index(
),然后将其与原始groupby
df合并以得到最终结果。关于如何将此规则转换为代码的任何想法?我很茫然。
答案 0 :(得分:2)
对于规则的第二部分,
-1,如果在至少48小时内得分低于8分之后,过去24小时的平均得分为<8分。
我想知道这是否意味着:
得分小于8的48小时可能是第一个障碍,然后平均得分小于8的随后的24小时是减少剂量的第二个障碍。
重要的是,如果没有这样的48小时周期数据,是否要解决第一个障碍就很难确定。
以下是在每个观察值的过去24小时和过去72小时之间生成最大分数的步骤。 (我很抱歉在这里写了些脏代码)
collect_set
并将此数据与原始数据集合并;
df.dateandtime = pd.to_datetime(df['dateandtime']) # change column type for ease of indexing
df = df.sort_values(by=['baby','dateandtime'])
df= df.reset_index(drop=True)
def filter_df_for_datetime_between_timedeltas(df, varname, base_datetime, time_gr= -72, time_le= -24, unit='h'):
df['hour_diff'] = df[varname] - base_datetime
return df[ (pd.Timedelta(time_gr, unit=unit) < df.hour_diff) &
(df.hour_diff < pd.Timedelta(time_le, unit=unit))]
df_24h_to_72h_max = pd.DataFrame()
for baby in list(df.baby.unique()):
df_baby = df[df.baby==baby]
for row in df_baby.iterrows():
base_datetime = row[1]['dateandtime']
df_row_24h_to_72h = filter_df_for_datetime_between_timedeltas(df_baby, 'dateandtime', base_datetime)
# print( df_row_24h_to_72h)
if len(df_row_24h_to_72h):
data_row = df_row_24h_to_72h[df_row_24h_to_72h.score==df_row_24h_to_72h.score.max()][::-1].iloc[0]
# print(data_row)
row_stat = dict(**row[1][:2],
max_24h_to_72h = data_row.score.max(),
max_24h_to_72h_time = data_row.dateandtime,
hour_diff = -data_row.hour_diff )
df_24h_to_72h_max = df_24h_to_72h_max.append(pd.DataFrame([row_stat]), ignore_index=True)
df_24h_to_72h_max
答案 1 :(得分:1)
如何尝试类似的事情:
Map(fdc, listDF_zoo, main = names(listDF_zoo))
成功的关键在于滚动。此处更多信息:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rolling.html
从这里开始,您只需做一个简单的函数即可检查相应的列并为每一行返回一个值。
答案 2 :(得分:1)
请仔细检查数学和逻辑,但我认为这是一条路。您绝对需要按婴儿分组,否则一个婴儿到下一个婴儿的数字会有所重叠。
df.dateandtime = pd.to_datetime(df['dateandtime']) # change column type for ease of indexing
df = df.set_index('dateandtime')
df.sort_index(inplace = True)
#Calculate conditions
df['sum_3_scores'] = df.groupby('baby')['score'].rolling(3).sum().reset_index(0,drop=True)
df['max_2_scores'] = df.groupby('baby')['score'].rolling(2).max().reset_index(0,drop=True)
df['max_48hr_score'] = df.groupby('baby')['score'].rolling('48h').mean().reset_index(0,drop=True)
#you don't nead to calculate the 24hr mean because the 48hr max is 8 the 24hr mean will also be < 8
#df['mean_24hr_score'] = df.groupby('baby')['score'].rolling('24h').mean().reset_index(0,drop=True)
#scoring logic
def score(data):
if data['sum_3_scores'] >= 24 or data['max_2_scores'] >= 12:
return 1
if data['max_48hr_score'] < 8: #if the score has been below 8 for 48 hours the average of the past 24 hours will be < 8
return -1
return 0
df['rule'] = df.apply(score, axis = 1)
#just for a nicely ordered output
df.reset_index().set_index(['baby','dateandtime']).sort_index()
产量:
score sum_3_scores max_2_scores max_48hr_score rule
baby dateandtime
A 2009-07-14 00:01:00 14 NaN NaN 14.000000 0
2009-07-16 21:00:00 4 NaN 14.0 4.000000 1
2009-07-17 00:01:00 10 28.0 10.0 7.000000 1
2009-07-17 06:00:00 5 19.0 10.0 6.333333 -1
2009-07-19 05:00:00 5 20.0 5.0 5.000000 -1
2009-07-19 09:00:00 11 21.0 11.0 8.000000 0
2009-07-19 13:00:00 7 23.0 11.0 7.666667 -1
2009-07-19 17:00:00 3 21.0 7.0 6.500000 -1
2009-08-02 17:00:00 6 16.0 6.0 6.000000 -1
B 2009-07-13 21:00:00 12 NaN NaN 12.000000 0
2009-07-14 18:00:00 4 NaN 12.0 8.000000 1
2009-07-15 00:04:00 6 22.0 6.0 7.333333 -1
2009-07-15 15:04:00 4 14.0 6.0 6.500000 -1
2009-07-16 00:01:00 7 17.0 7.0 5.250000 -1
2009-07-16 06:00:00 6 17.0 7.0 5.400000 -1
2009-07-18 13:00:00 4 17.0 6.0 4.000000 -1
2009-07-19 01:00:00 6 16.0 6.0 5.000000 -1
2009-07-20 17:00:00 6 16.0 6.0 6.000000 -1