在熊猫数据框中计算每日总金额

时间:2019-09-19 18:43:10

标签: python-3.x pandas dataframe

我有一个如下所示的数据框,我正在尝试计算每种药物的日剂量。在下表中,我有一种药物,但在实际表中,我有多种药物。

让我对表格和场景进行简要说明。 ID列是唯一的患者ID,“开始和结束”列表示药物以该速率开始和结束的时间,“小时”列表示该ID从开始到结束之间的小时数,“速率”列显示的是什么速率在该时间段内使用该ID的药物。该表格的设计方式是每个ID的每个费率都有一个开始和结束日期。

在医院中,如果他们要计算每日总剂量,则要从今天上午7点到第二天上午7点进行计算,而不是从午夜到午夜进行计算。

  ID           START                   END            DRUG     RATE  HOURS
15114299  2011-03-18 18:23:00  2011-03-19 20:59:59  morphine   0.03   26.6
15114299  2011-03-19 21:00:00  2011-03-20 01:29:59  morphine    0.1   4.4
15340823  2011-02-18 16:00:00  2011-02-19 03:09:59  morphine    0.1   11.16
15340823  2011-02-19 15:30:00  2011-02-19 21:59:59  morphine    0.05  6.49
15621352  2011-04-20 03:44:00  2011-04-20 13:41:59  morphine    0.05  9.96
15621352  2011-04-20 13:42:00  2011-04-20 23:59:59  morphine    0.5   10.29
15775791  2011-07-21 19:00:00  2011-07-24 03:59:59  morphine    0.1   56.99
15775791  2011-07-24 04:00:00  2011-07-24 14:14:59  morphine    0.05  10.24
15947559  2011-07-05 19:40:00  2011-07-06 05:43:59  morphine    0.1   10.06
15947559  2011-07-06 05:44:00  2011-07-09 01:59:59  morphine    0.15  68.26
15947559  2011-07-09 02:00:00  2011-07-09 18:59:59  morphine    0.1   16.99
15947559  2011-07-14 19:30:00  2011-07-15 18:29:59  morphine    0.1   22.99
15947559  2011-07-15 18:30:00  2011-07-17 02:59:59  morphine    0.15  32.49
15947559  2011-07-17 03:00:00  2011-07-17 08:59:59  morphine    0.1   5.99
15947559  2011-07-17 09:00:00  2011-07-17 16:59:59  morphine    0.075 7.99

在示例数据框中可以看到,第一种药物治疗了26.6小时,我想要做的是将该记录分成两部分,如下所示,并有一个day列将有助于分组并求和最后的每一天。

期望的DF:

  ID           START                   END            DRUG     RATE     HOURS   Days
15114299  2011-03-18 18:23:00  2011-03-19 06:59:59  morphine   0.03     12.62   Day1
15114299  2011-03-19 07:00:00  2011-03-19 20:59:59  morphine   0.03     14      Day2
15114299  2011-03-19 21:00:00  2011-03-20 01:29:59  morphine    0.1     4.5     Day2

15340823  2011-02-18 16:00:00  2011-02-19 03:09:59  morphine    0.1     11.16   Day1
15340823  2011-02-19 15:30:00  2011-02-19 21:59:59  morphine    0.05    6.49    Day2

15621352  2011-04-20 03:44:00  2011-04-20 06:59:59  morphine    0.05    3.27    Day1
15621352  2011-04-20 07:00:00  2011-04-20 13:41:59  morphine    0.05    6.70    Day2
15621352  2011-04-20 13:42:00  2011-04-20 23:59:59  morphine    0.5     10.29   Day2

15775791  2011-07-21 19:00:00  2011-07-22 06:59:59  morphine    0.1     12      Day1
15775791  2011-07-22 07:00:00  2011-07-23 06:59:59  morphine    0.1     24      Day2        
15775791  2011-07-23 07:00:00  2011-07-24 03:59:59  morphine    0.1     21      Day3
15775791  2011-07-24 04:00:00  2011-07-24 06:59:59  morphine    0.05    3       Day3
15775791  2011-07-24 07:00:00  2011-07-24 14:14:59  morphine    0.05    7.25    Day4

15947559  2011-07-05 19:40:00  2011-07-06 05:43:59  morphine    0.1     10.06   Day1
15947559  2011-07-06 05:44:00  2011-07-06 06:59:59  morphine    0.15    1.27    Day1 
15947559  2011-07-06 07:00:00  2011-07-07 06:59:59  morphine    0.15    24      Day2
15947559  2011-07-07 07:00:00  2011-07-08 06:59:59  morphine    0.15    24      Day3
15947559  2011-07-08 07:00:00  2011-07-09 01:59:59  morphine    0.15    19      Day4
15947559  2011-07-09 02:00:00  2011-07-09 06:59:59  morphine    0.1     5       Day4
15947559  2011-07-09 07:00:00  2011-07-09 18:59:59  morphine    0.1     12      Day5
15947559  2011-07-14 19:30:00  2011-07-15 06:59:59  morphine    0.1     11.50   Day6
15947559  2011-07-15 07:00:00  2011-07-15 18:29:59  morphine    0.1     11.50   Day7
15947559  2011-07-15 18:30:00  2011-07-16 06:59:59  morphine    0.15    12.50   Day7
15947559  2011-07-16 07:00:00  2011-07-17 02:59:59  morphine    0.15    20      Day8
15947559  2011-07-17 03:00:00  2011-07-17 06:59:59  morphine    0.1     4       Day8
15947559  2011-07-17 07:00:00  2011-07-17 08:59:59  morphine    0.1     2       Day9
15947559  2011-07-17 09:00:00  2011-07-17 16:59:59  morphine    0.075   8       Day9

(为了更加清楚和理解,我在两个ID之间创建了空格)

我尝试了以下代码。

test = pd.concat([pd.DataFrame({'START': pd.date_range(row['START'], row['END'], freq='D'),
               'PERSON_ID': row['ID'],
               'DRUG': row['DRUG'], 
               'RATE': row['RATE']}, columns=['ID', 'START', 'DRUG', 'RATE'])
           for i, row in df.iterrows()], ignore_index=False)

,但这会以以下方式创建数据框。

ID              START          DRUG       RATE
15114299    2011-03-18 18:23:00 morphine    0.03
15114299    2011-03-19 18:23:00 morphine    0.03
15114299    2011-03-19 21:00:00 morphine    0.1
15340823    2011-02-18 16:00:00 morphine    0.1
15340823    2011-02-19 15:30:00 morphine    0.05
15621352    2011-04-20 03:44:00 morphine    0.05
15621352    2011-04-20 13:42:00 morphine    0.5
15775791    2011-07-21 19:00:00 morphine    0.1
15775791    2011-07-22 19:00:00 morphine    0.1
15775791    2011-07-23 19:00:00 morphine    0.1
15775791    2011-07-24 04:00:00 morphine    0.05
15947559    2011-07-05 19:40:00 morphine    0.1
15947559    2011-07-06 05:44:00 morphine    0.15
15947559    2011-07-07 05:44:00 morphine    0.15
15947559    2011-07-08 05:44:00 morphine    0.15
15947559    2011-07-09 02:00:00 morphine    0.1
15947559    2011-07-14 19:30:00 morphine    0.1
15947559    2011-07-15 18:30:00 morphine    0.15
15947559    2011-07-16 18:30:00 morphine    0.15
15947559    2011-07-17 03:00:00 morphine    0.1
15947559    2011-07-17 09:00:00 morphine    0.075

如果有人可以帮助我解决这个问题,我将非常感谢。很高兴提供其他详细信息。

1 个答案:

答案 0 :(得分:2)

从定义此类变量开始:

h7 = pd.Timedelta('7H')
s1 = pd.Timedelta('1S')

(将使用多次)。

要将每一行“扩展”为一系列行(每天), 定义以下功能:

def expand(row):
    tm1, tm2 = row.START, row.END
    t1 = tm1 if type(tm1).__name__ == 'Timestamp' else pd.to_datetime(tm1)
    t2 = tm2 if type(tm2).__name__ == 'Timestamp' else pd.to_datetime(tm2)
    rng = pd.date_range(start=t1 - h7, end=t2 - h7, freq='1D', closed='right',
        normalize=True) + pd.Timedelta('7H')
    ind = pd.DatetimeIndex([t1, *rng, t2 + s1])
    res = pd.DataFrame({'ID': row.ID, 'START': ind[:-1], 'END': ind[1:] - s1,
        'DRUG': row.DRUG, 'RATE': row.RATE})
    res['HOURS'] = (res.END - res.START).dt.total_seconds().div(3600).round(2)
    return res

并应用它,创建结果表:

df2 = pd.concat(df.apply(expand, axis=1).tolist(), ignore_index=True)

现在,没有列。

然后添加列,执行:

df2['Days'] = 'Day' + ((df2.START - h7).dt.date - df2.groupby('ID')
    .START.transform('first').dt.date).dt.days.add(1).astype(str)

“天”号(“ <天”之后的“ ”)是当前日期之间的差 以及第一行的日期+ 1。

由于从当前日期减去了 h7 ,因此此代码可以正常工作, 即使在Midnignt和7点之间发生更改。

要显示结果,请运行:

df2.sort_values('ID')

要跟踪该解决方案的思想,请分别运行每个语句,然后 查看结果。

相关问题