带有滚动窗口的熊猫功能

时间:2020-10-05 14:09:49

标签: python pandas dataframe

我正在研究一个新生儿项目,长话短说,就是根据给定时间点的症状给新生儿分配一定的分数。根据它们的分数随时间变化的方式,我们决定是增加药物剂量,保持剂量不变还是断奶。我们用数字+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,则至少在48小时后才能产生-1)。例如,我增加了“ 2009-07-17 00:01:00”的剂量,但是代码说降低了“ 48小时”的“ 2009-07-18 19:00:00”的剂量。因此,我知道问题出在我的“ def score(data)”函数中,但是我不确定如何修改此函数,以使它知道如果距时间点少于48小时,则不会产生-1。增加剂量。

1 个答案:

答案 0 :(得分: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'])
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")


然后您可以根据此新列计算分数