请帮助从今天开始为四列中的每一行项目查找下一个日期,如下所示。我已经坚持了一段时间了。
InDate1 InDate2 InDate3 InDate4
284075 2018-03-07 2018-09-07 2019-03-07 2019-01-21
334627 2018-03-07 2018-09-07 2019-03-07 2019-09-07
请检查这个。
首先将日期值堆叠成行,以便我们可以应用最小值和今天的比较。
df1 = df.stack().reset_index()
df1.columns = ["ID", "Field", "Date"]
然后用今天过滤数据并找出最小日期。
df1 = df1[df1.Date > datetime.datetime.now()].groupby("ID").agg("min").reset_index()
然后透视结果日期,在它之前,只需分配一个静态值来确定为单列标题而不是 IntDate1..etc。
df1.Field = "MinValue"
df1 = df1.pivot(index="ID", columns="Field", values="Date").reset_index()
最后将最小日期值数据框与原始数据框合并。
df = df.merge(df1, how="left")
对于每一行,找到包含最近未来日期的列:
import pandas as pd
s = (df.apply(pd.to_datetime) # If not already datetime
.apply(lambda x: (x - pd.to_datetime('today')).dt.total_seconds())
.where(lambda x: x.gt(0)).idxmin(1))
print(s)
#284075 InDate3
#334627 InDate3
#dtype: object
然后查找每一行的值:
df.lookup(s.index, s)
#array(['2019-03-07', '2019-03-07'], dtype=object)
要详细说明它的作用,您可以分别查看每个部分的作用
首先,确定你DataFrame和今天之间的时间差。.apply(pd.to_datetime)将所有内容转换为 adatetime以便它可以对日期进行算术运算,第二个 apply 找到时间差,将其从 a 转换timedelta为秒数,这只是一个浮点数。(不知道为什么简单df - pd.to_datetime('today')不能很好地工作并且需要申请)
s = (df.apply(pd.to_datetime) # If not already datetime
.apply(lambda x: (x - pd.to_datetime('today')).dt.total_seconds()))
print(s)
InDate1 InDate2 InDate3 InDate4
284075 -2.769565e+07 -1.179805e+07 3.840347e+06 -4.765262e+04
334627 -2.769565e+07 -1.179805e+07 3.840347e+06 1.973795e+07
未来的日期会有一个正时差,所以我.where只找到具有正值的单元格,将其他所有内容替换为NaN
s = s.where(lambda x: x.gt(0))
# Could use s.where(s.gt(0)) here since `s` is defined
print(s)
InDate1 InDate2 InDate3 InDate4
284075 NaN NaN 3.840347e+06 NaN
334627 NaN NaN 3.840347e+06 1.973795e+07
然后.idxmin(axis=1)将为每一行(axis = 1)返回具有最小值(忽略NaN)的列,这是最近的未来日期。
s.idxmin(1)
print(s)
284075 InDate3
334627 InDate3
dtype: object
最后,DataFrame.lookup在该单元格中查找原始日期是不言自明的。