查找具有不同格式日期的 2 列之间的绝对差异作为天数

Find absolute difference between 2 columns with dates of different formats as number of days

我需要找出日期在 python 中的 2 列之间的绝对天数差异。 这在 excel 中非常简单,但我想要在 python.

我有一个 xlsx 文件,我已将其读取到 python 数据帧(使用 pd.read_excel),示例数据如下所示: 这些列具有 ddmmyyyy/dmmyyyy.

纯文本格式的日期详细信息

A B
1102012
26071993 27122007
28062010 3122015
16012010 21022016
02082015 14092010

现在我需要创建一个新列 C,其中包含 A 和 B 之间的绝对天数差异。A 可以小于或大于 B。
如果 B 为空,那么它应该考虑当前日期来计算天数。但是 A 不会有 empty/NULL 个值。

因此输出将是天数之差:

C
2432
5267
1984
2227
1783

我采用的方法是:

  1. 将 A 和 B 转换为 8 位数字,因为我们在 A 和 B 的某些值中只有 7 位数字 - 使用 df['A'].apply(lambda x: '{0:0>8}'.format(x))
  2. 使用 pd.to_datetime
  3. 将 A 转换为日期时间字段
  4. 通过复制 B 值和所有非 NULL 日期值创建另一个临时列,例如 CC(即用当前日期替换 NULL/empty)
  5. 然后求A和CC的绝对差(天数)

我卡在了第三步,无法继续。有没有更简单的方法来做到这一点?

首先格式化选项是个好主意。避免混淆是日还是月。

# Recreate dataframe
df = pd.DataFrame([["1102012", pd.np.NaN],["26071993","27122007"],
                   ["28062010","3122015"],["16012010","21022016"],
                   ["02082015","14092010"]], columns=["A","B"]) 
print(df)
>>>
          A         B
0   1102012       NaN
1  26071993  27122007
2  28062010   3122015
3  16012010  21022016
4  02082015  14092010

print(df.dtypes)
>>>
A    object
B    object
dtype: object

所以我们正在使用的数据框在上面。数据类型都是object(字符串)。如果你能确认这一步就好了,因为其他一切都源于这里。

# convert some datetimes
# Assumption is that column A is not sparse - there are no NaNs
# Column B can be NaN so make it today if so
m = df["B"].isnull()
df.loc[m, "B"] = pd.datetime.now().strftime("%d%m%Y") 
print(df)
>>>
          A         B
0   1102012  03062019
1  26071993  27122007
2  28062010   3122015
3  16012010  21022016
4  02082015  14092010

# now we zero pad some numbers
df['A'] = df['A'].apply(lambda x: '{0:0>8}'.format(x))
df['B'] = df['B'].apply(lambda x: '{0:0>8}'.format(x))
print(df)
>>>
          A         B
0  01102012  03062019
1  26071993  27122007
2  28062010  03122015
3  16012010  21022016
4  02082015  14092010

然后使用to_datetime:

df["A"] = pd.to_datetime(df["A"], format="%d%m%Y")
df["B"] = pd.to_datetime(df["B"], format="%d%m%Y")
print(df)
>>>
           A          B
0 2012-10-01 2019-06-03
1 1993-07-26 2007-12-27
2 2010-06-28 2015-12-03
3 2010-01-16 2016-02-21
4 2015-08-02 2010-09-14

print(df.dtypes)
>>>
A    datetime64[ns]
B    datetime64[ns]
dtype: object

然后差异

df["Diff"] = (df["A"] - df["B"]).abs()
print(df)
>>>
           A          B      Diff
0 2012-10-01 2019-06-03 2436 days
1 1993-07-26 2007-12-27 5267 days
2 2010-06-28 2015-12-03 1984 days
3 2010-01-16 2016-02-21 2227 days
4 2015-08-02 2010-09-14 1783 days

# or
df["Diff"] = (df["A"] - df["B"]).abs().dt.days
print(df)
>>>
           A          B  Diff
0 2012-10-01 2019-06-03  2436
1 1993-07-26 2007-12-27  5267
2 2010-06-28 2015-12-03  1984
3 2010-01-16 2016-02-21  2227
4 2015-08-02 2010-09-14  1783

编辑解释错误

正如你所说的评论中的错误。这意味着您的列 A 不是 dtype object。它是 int32int64。 运行 此命令用于确认(我更改了示例数据列 A dtype 以演示错误):

df.dtypes

Out[2866]:
A     int32
B    object
dtype: object

在使用str.zfill之前,您需要将df更改为object,如下所示:

df = df.astype(str)

Out[2870]:
A    object
B    object
dtype: object

将 dtype 转换为 object 后,一切正常。


zfill(8) 将 0 填充到字符串,并使用 pd.to_datetimecoerce 将它们转换为日期时间,并在 NaT 上使用 filna 将它们转换为日期时间。接下来,做减法 AB,得到 abs 并从 timedelta

得到 days

注意:添加pre-process以使用astype(str)

df dtype转换为object
df = df.astype(str) 
df1 = df.apply(lambda x: pd.to_datetime(x.str.zfill(8), format='%d%m%Y', errors='coerce')).fillna(pd.datetime.today().date())
df1.A.sub(df1.B).abs().dt.days

Out[2599]:
0    2432
1    5267
2    1984
3    2227
4    1783
dtype: int64