Pandas:基于行中的值与列添加进行日期比较

时间:2016-04-11 14:23:23

标签: python excel date pandas

我有许多类似格式的excel文件:

|name| email| cat1| cat2| cat3
 smith email 01JAN2016 01JAN2014 01JAN2015

前两列包含字符串(名称和电子邮件地址),而以下每列包含每个人在cat(x)中完成每个项目的日期。

我想与current_date进行比较,添加新列' status'它将具有符合要求的价值'或者“拖欠”'根据一行中的任何日期是否在当前日期之前,然后将新数据框输出到Excel电子表格。

我最初的尝试让我过滤了“老年人”。但是,当我试图使用条件一切开始破坏时添加一个列时,相当容易约会:

import pandas as pd
import numpy as np
import datetime

current_date = datetime.datetime.now()
writer = pd.ExcelWriter('pd_output.xlsx', engine='xlsxwriter', datetime_format= 'mmm d yyy')

df = pd.read_excel(tracker,'Sheet1')

print(df.values)    # Displays dates as 'Timestamp('2016-01-01 00:00:00') any value which is < current_date displays as 'True' else 'False'

print(df < current_date)  # removes dates that are not older than current_date but does not delete column, ie someone with no old dates will still show up with column 3+ being blank

# a couple version of what I have been trying - unsuccessfully
df['Status'] = np.where(df[df < current_date], 'delinquent', 'compliant'  # error: 'wrong number of items passed

df['Status'] = np.where(df == 'True', 'delinquent', 'compliant'  # error: 'str' obj has no attr 'view'  

df['Status' = df.Set.map(lambda x: 'delinquent' if 'True' in df else 'compliant'  # from another post - error 'no attr 'Set' or 'map'

  # send to output excel
  df.to_excel(writer,sheet_name='Sheet1')

我想要一个输出显示带有&#39;状态&#39;的行。列添加显示有违规日期的地方&#39;在行内 - 引入符合条件的&#39;或者拖欠。&#39;我觉得我正在使我的比较不正确(使用True而不是另一个.where)但似乎无法做到正确。

1 个答案:

答案 0 :(得分:3)

如果要基于一个或多个其他列的值创建新列,通常使用apply函数之一。当函数是多列时,就像这里的情况一样,使用DataFrame.apply。以下是我认为您要做的事情的近似值:

df['Status'] = df.apply (
    lambda df : (
      'delinquent' 
          if any (df[i] < current_date for i in ("cat1","cat2","cat3")) 
       else 'compliant'
    ) ,
    axis = 1
)

(仅供参考我从你的逻辑中认为,“逾期”意味着日期在当前日期之前,如果我错了,请将<符号反转为>我的上述内容。)< / p>

让我们解开一点。 apply将向量化函数应用于整个数据帧。我们需要应用于整个数据框,因为我们正在查看多个列;不久,我们将指定哪些。该函数是我们定义的lambdaaxis = 1参数告诉apply将lambda应用于每一行(这不是默认值,默认值为axis = 0,它适用于每一列 - 不是我们想要的)。 lambda本身按名称查看所有3个日期列,如果其中任何一个列在当前日期之前,则返回“拖欠”。我将any()与内部的生成器表达式一起使用,以避免编写类似if df["cat1"] < current_date or df["cat2"] < current_date or df["cat3"] < current_date之类的苦差事等等。

请注意,所有这些都取决于您的3个日期列属于datetime类型 - 我假设它们是。

如果您只有一个日期列,例如“cat1”,则可以在该列上使用稍微简单的Series.apply

df['Status'] = df['cat1'].apply (
    lambda x : 'delinquent' if x < current_date else 'compliant' 
)

这样做的理由是功能更简单,缺少axis参数。因此,一般情况下,人们在应用只有一列的函数时会使用Series.apply,而如果函数的列数超过一列,则使用DataFrame.apply