熊猫:根据另一行的值删除行

时间:2019-02-27 19:02:10

标签: python pandas data-manipulation

我有一个熊猫数据框,其列名称为“ ID”,“日期时间”,“药物”。现在,我正在尝试在给定的时间内消除所有与美沙酮药物有关的吗啡药物行。

例如:

ID-66531在2013-02-19 20:54接受了第一个美沙酮药物治疗。由于美沙酮和吗啡都是止痛药,因此药物的作用是相同的。因此,如果每个ID组在吗啡用药的24小时内给予美沙酮,我将尝试消除吗啡用药的行。因此,对于ID-66531,如果这种情况下的吗啡在美沙酮的24小时时间范围内(2013年2月18日20:53和2013年2月19日20:54之间),我希望删除这些记录身份组

实际数据框:

64347   2012-02-15 19:24:00 morphine
64347   2012-02-15 22:54:00 morphine
64347   2012-02-16 05:50:00 morphine
64347   2012-02-16 12:47:00 oxyCODONE
64347   2012-10-20 05:03:00 morphine
64347   2012-10-21 15:10:00 morphine
64347   2012-10-21 19:06:00 morphine
64347   2012-11-16 16:00:00 morphine
64990   2012-09-21 07:10:00 oxyCODONE
64990   2012-09-21 16:45:00 fentaNYL
64990   2012-09-21 23:21:00 oxyCODONE
64990   2012-09-22 15:40:00 oxyCODONE
66531   2012-12-18 08:31:00 acetaminophen-HYDROcodone
66531   2012-12-18 17:44:00 acetaminophen-HYDROcodone
66531   2013-02-18 22:36:00 morphine
66531   2013-02-19 05:07:00 morphine
66531   2013-02-19 10:13:00 morphine
66531   2013-02-19 15:27:00 morphine
66531   2013-02-19 17:33:00 oxyCODONE
66531   2013-02-19 19:20:00 acetaminophen-HYDROcodone
66531   2013-02-19 20:54:00 methadone
66531   2013-02-20 06:46:00 methadone
66531   2013-02-20 13:21:00 methadone
66531   2013-02-20 22:18:00 methadone

期望的数据框:

64347   2012-02-15 19:24:00 morphine
64347   2012-02-15 22:54:00 morphine
64347   2012-02-16 05:50:00 morphine
64347   2012-02-16 12:47:00 oxyCODONE
64347   2012-10-20 05:03:00 morphine
64347   2012-10-21 15:10:00 morphine
64347   2012-10-21 19:06:00 morphine
64347   2012-11-16 16:00:00 morphine
64990   2012-09-21 07:10:00 oxyCODONE
64990   2012-09-21 16:45:00 fentaNYL
64990   2012-09-21 23:21:00 oxyCODONE
64990   2012-09-22 15:40:00 oxyCODONE
66531   2012-12-18 08:31:00 acetaminophen-HYDROcodone
66531   2012-12-18 17:44:00 acetaminophen-HYDROcodone
66531   2013-02-19 17:33:00 oxyCODONE
66531   2013-02-19 19:20:00 acetaminophen-HYDROcodone
66531   2013-02-19 20:54:00 methadone
66531   2013-02-20 06:46:00 methadone
66531   2013-02-20 13:21:00 methadone
66531   2013-02-20 22:18:00 methadone

我尝试过的事情:

我创建了一个timediff列,该列获取两个记录之间的时间差。

df['timediff'] = df.sort_values(by= 'datetime').groupby('ID')['datetime'].diff()

然后我将24小时分配给变量x

x = '24:00:00'并尝试使用以下代码删除吗啡

df = df.groupby('ID').apply(lambda x : x.loc[~(x['Medication'] == 'morphine')<x]

但是此代码删除了吗啡记录,而与给定时间的美沙酮药物治疗无关。

如果能对此有所帮助,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

>>> names = ['Id', 'Datetime', 'Drug']
>>> df = pd.read_csv('drugs.csv', names=names, parse_dates=['Datetime'])
>>> df

    Id      Datetime                Drug
0   66531   2012-12-18 08:31:00     acetaminophen-HYDROcodone
1   66531   2012-12-18 17:44:00     acetaminophen-HYDROcodone
2   66531   2013-02-18 22:36:00     morphine
3   66531   2013-02-19 05:07:00     morphine
4   66531   2013-02-19 10:13:00     morphine
5   66531   2013-02-19 15:27:00     morphine
6   66531   2013-02-19 17:33:00     oxyCODONE
7   66531   2013-02-19 19:20:00     acetaminophen-HYDROcodone
8   66531   2013-02-19 20:54:00     methadone
9   66531   2013-02-20 06:46:00     methadone
10  66531   2013-02-20 13:21:00     methadone
11  66531   2013-02-20 22:18:00     methadone

然后,循环浏览所有行组合。它有效,但不是最有效的解决方案。如果您的数据集非常大,则可能需要考虑一种更优雅的方法。

drop_idx = set([])
for idx_early, row_early in df.iterrows():
    for idx_late, row_late in df.iterrows():
        if (row_early['Datetime'] + pd.DateOffset(hours=24) > row_late['Datetime'] and
            row_early['Datetime'] < row_late['Datetime'] and
            row_early['Drug'] == 'morphine' and
            row_late['Drug'] == 'methadone' and
            row_early['Id'] == row_late['Id']):
            drop_idx.add(idx_early)

现在,删除已标识的行并打印结果。

>>> df.drop(index=drop_idx)

    Id      Datetime                Drug
0   66531   2012-12-18 08:31:00     acetaminophen-HYDROcodone
1   66531   2012-12-18 17:44:00     acetaminophen-HYDROcodone
6   66531   2013-02-19 17:33:00     oxyCODONE
7   66531   2013-02-19 19:20:00     acetaminophen-HYDROcodone
8   66531   2013-02-19 20:54:00     methadone
9   66531   2013-02-20 06:46:00     methadone
10  66531   2013-02-20 13:21:00     methadone
11  66531   2013-02-20 22:18:00     methadone

答案 1 :(得分:1)

这是我想出的:

import pandas
df = pandas.read_csv('test.tsv', header=None, sep='\s+',
                     parse_dates = [['date', 'time']],
                     names=['patient_id', 'date', 'time','drug'])

to_drop = set()
for _, patient in df.groupby('patient_id'):
    meth_times = patient.loc[patient['drug'] == 'methadone']['date_time']
    morph_doses = patient.loc[patient['drug'] == 'morphine']
    for i, md in morph_doses.iterrows():
        for mt in meth_times:
            days_elapsed = (mt - md['date_time']).days
            if days_elapsed < 1:
                to_drop.add(i)
                break

df = df[~df.index.isin(to_drop)]

与@ulmefors建议的答案一样,这在每个吗啡/美沙酮行上重复进行迭代,因此效率低下,但是除非您使用庞大的数据集,否则它应该足够快地完成工作,这样就可以微不足道。 (但是与其他答案不同,它只是在每个患者的吗啡/美沙酮剂量内重复多次,而不是通过所有可能的行组合进行重复操作)