在熊猫数据框上带有日期的条件

时间:2019-12-11 12:04:56

标签: python python-3.x pandas

我想创建一个根据某些条件标记行的函数。

它不起作用,我认为是由列的格式引起的。

函数是:

tolerance=5

def pmm_m2_rag(data):

    if  data['m2'] == data['TP_M2'] and data['m6p'] + pd.to_timedelta(tolerance,unit='D') <= data['latedate']:
        return 'GREEN'


    elif data['m2']!= data['TP_M2'] and data['m6p'] + pd.to_timedelta(tolerance,unit='D') < data['latedate']:
        return 'AMBER'


    elif data['m2']!= None and data['m6p'] + pd.to_timedelta(tolerance,unit='D') > data['latedate']:
        return 'RED'

数据框为:

                m2       TP_M2         m6p          latedate         
0       2019-11-28  2019-10-29  2020-02-21        2020-02-25       
1       2019-11-28  2019-10-29  2020-02-21        2020-02-25       
2       2019-11-28  2019-11-28  2020-02-09        2020-02-17       
3       2019-11-28  2019-11-28  2020-02-29        2020-02-17

数据类型为:

m2                  object
TP_M2               object
m6p                 object
latedate    object
dtype: object

预期输出:

                m2       TP_M2         m6p          latedate         RAG
0       2019-11-28  2019-10-29  2020-02-21        2020-02-25       AMBER
1       2019-11-28  2019-10-29  2020-02-21        2020-02-25       AMBER
2       2019-11-28  2019-11-28  2020-02-09        2020-02-17       GREEN
3       2019-11-28  2019-11-28  2020-02-29        2020-02-17         RED

2 个答案:

答案 0 :(得分:1)

一个选项,可以在进行以下object比较之前将datetime转换为datetime

from datetime import datetime
tolerance=5

def pmm_m2_rag(data):
    #m2 = datetime.strptime(data['m2'],'%Y-%m-%d')
    #m6p = datetime.strptime(data['m6p'],'%Y-%m-%d')
    #latedate = datetime.strptime(data['latedate'],'%Y-%m-%d')
    #TP_M2 = datetime.strptime(data['TP_M2'],'%Y-%m-%d')
    m2 = datetime.strptime(str(data['m2']),'%Y-%m-%d')
    m6p = datetime.strptime(str(data['m6p']),'%Y-%m-%d')
    latedate = datetime.strptime(str(data['latedate']),'%Y-%m-%d')
    TP_M2 = datetime.strptime(str(data['TP_M2']),'%Y-%m-%d')
    if  m2 == TP_M2 and m6p + pd.to_timedelta(tolerance,unit='D') <= latedate:
        return 'GREEN'


    elif m2!= TP_M2 and m6p + pd.to_timedelta(tolerance,unit='D') < latedate:
        return 'AMBER'


    elif m2!= None and m6p + pd.to_timedelta(tolerance,unit='D') > latedate:
        return 'RED'
df['RAG'] = df.apply(pmm_m2_rag, axis=1)

答案 1 :(得分:1)

首先,您的代码中的某些内容似乎是错误的。这个

... unit='D') <= data['latedate'] < data['m6p'] ...

链接比较绝对是错误的。

然后在您的条件中使用 AMBER or的两个子句是相同的。这也没有道理。

除此之外,您还应该将列的数据类型转换为类型datetime。例如。通过:

data = data.applymap(pd.to_datetime)

这取决于您从数据库中读取数据的类型。

在那之后,基本上有两个选择。您可以编写一个仅占一行,计算值并返回 color 的函数。然后逐行应用此功能。

另一个(更快更可取的)选择是并行计算“ RAG”列。

这可以通过在您上面编写的条件下使用numpy.where来完成。 请注意,datafram列之间的and必须写为&or|

类似的事情应该起作用:

import numpy as np
def pmm_m2_rag(data):
    green_filter = (data.m2 == data.TP_M2) & \
        (data.m6p + pd.to_timedelta(tolerance,unit='D') <= data.latedate)

    amber_filter = (data.m2 != data.TP_M2) & \
        (data.m6p + pd.to_timedelta(tolerance,unit='D') < data.latedate) | \
        (data.latedate > data.m6p + pd.to_timedelta(tolerance,unit='D'))

    red_filter = (data.m2 != pd.NaT) & \
        (data.m6p + pd.to_timedelta(tolerance,unit='D') > data.latedate)

    data['RAG'] = np.where(green_filter, 'GREEN', np.where(amber_filter, 'AMBER', np.where(red_filter, 'RED', '')))

np.where的语法是

np.where(<CONDITION>, true-clause, false-clause)