我有许多类似格式的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)但似乎无法做到正确。
答案 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
将向量化函数应用于整个数据帧。我们需要应用于整个数据框,因为我们正在查看多个列;不久,我们将指定哪些。该函数是我们定义的lambda
。 axis = 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
。