查找具有不同格式日期的 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
我采用的方法是:
- 将 A 和 B 转换为 8 位数字,因为我们在 A 和 B 的某些值中只有 7 位数字 - 使用
df['A'].apply(lambda x: '{0:0>8}'.format(x))
- 使用
pd.to_datetime
将 A 转换为日期时间字段
- 通过复制 B 值和所有非 NULL 日期值创建另一个临时列,例如 CC(即用当前日期替换 NULL/empty)
- 然后求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
。它是 int32
或 int64
。 运行 此命令用于确认(我更改了示例数据列 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_datetime
和 coerce
将它们转换为日期时间,并在 NaT
上使用 filna
将它们转换为日期时间。接下来,做减法 A
和 B
,得到 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
我需要找出日期在 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
我采用的方法是:
- 将 A 和 B 转换为 8 位数字,因为我们在 A 和 B 的某些值中只有 7 位数字 - 使用
df['A'].apply(lambda x: '{0:0>8}'.format(x))
- 使用
pd.to_datetime
将 A 转换为日期时间字段
- 通过复制 B 值和所有非 NULL 日期值创建另一个临时列,例如 CC(即用当前日期替换 NULL/empty)
- 然后求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
。它是 int32
或 int64
。 运行 此命令用于确认(我更改了示例数据列 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_datetime
和 coerce
将它们转换为日期时间,并在 NaT
上使用 filna
将它们转换为日期时间。接下来,做减法 A
和 B
,得到 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