1、背景描述:(日期加减计算经常遇到的报错)
数据分析中要对日期进行计算,经常遇到这些报错或问题:
- TypeError: cannot subtract DatetimeArray from ndarray
- TypeError: unsupported operand type(s) for -: ‘DatetimeArray’ and ‘datetime.date’
- TypeError: unsupported operand type(s) for -: ‘DatetimeArray’ and ‘str’
2、问题根本原因及解决方法:
根本原因:两个参与计算的日期类型不一致导致。通常情况是一个类型是datetime.date, 而另一个是timestamps.Timestamp。这样就导致了上述的这些报错信息!
解决方法:
- 统一转换为日期类型(datetime.date)来计算
df[“date”] = df[“date”].map(lambda x: datetime.strptime(x, “%Y.%m.%d”).date()) - 统一转换为时间戳(timestamps.Timestamp)的类型来计算;
df[“date”] = df[“date”].map(lambda x: datetime.strptime(x, “%Y.%m.%d”)) - 直接使用pd.to_datetime() 函数来将所有日期转换为时间戳类型来计算
3、问题解决(示例代码 python)
3.1 建立含有日期的数据表(任务:与输入的登录日期“2021/10/15”进行计算)
from datetime import *
# 3.1 建立含日期的数据表
set1 = {"date1": ["2021.09.15", "2021.09.17", "2020.03.20", "2021.01.15", "2020.01.25"],
"values": [10, 50, 20, 40, 30]}
df = pd.DataFrame(set1, columns=["date1", "values"])
上述表格中的日期类型是“str", 是不能直接进行计算的,需要进行类型的转换。
3.2 日期类型的转换
#3.2 将数据表中的日期从"str"转换为日期类型
df["date1"] = df["date1"].map(lambda x: datetime.strptime(x, "%Y.%m.%d"))
print("date1的数据类型:", type(df["date1"][1]))
df["date1"]
一般情况下,将日期转换后通常会认为这个"date1"的类型是日期类型(datetime.date), 但是它实际是日期时间的类型(dtype: datetime64[ns] = “timestamps.Timestamp”),因为很容易被忽视,这就是我们遇到上述报错的根本原因之一!
正确的转换为日期类型(datetime.date)方式为:
# 正确转换为日期类型(datetime.date)的方式:
df["date1"] = df["date1"].map(lambda x: datetime.strptime(x, "%Y.%m.%d").date())
print("date1的数据类型:", type(df["date1"][1]))
df
了解了问题的根本原因,则正确的解决方法有以下3种:
3.3 解决方法一:统一将日期转换为datetime.date 的日期类型来计算:
# 3.3 方式一:转换为datetime.date的日期类型来计算
df["date1"] = df["date1"].map(lambda x: datetime.strptime(x, "%Y.%m.%d").date())
print("date1的数据类型:", type(df["date1"][1]))
# 输入日期,并计算之间的日期差值
login = "2021.10.15"
login = datetime.strptime(login, "%Y.%m.%d").date()
df["time"] = login - df["date1"]
df
3.4 解决方法二:统一转换为时间戳(timestamps.Timestamp)的类型来计算:
# 3.4 方式二:转换为timestamps.Timestamp的时间类型来计算
df["date1"] = df["date1"].map(lambda x: datetime.strptime(x, "%Y.%m.%d"))
print("date1的数据类型:", type(df["date1"][1]))
# 输入日期,并计算之间的日期差值
login = "2021.10.15"
login = datetime.strptime(login, "%Y.%m.%d")
df["time"] = login - df["date1"]
df
3.5 解决方法三:无论原来的日期类型是什么,直接使用pd.to_datetime() 函数来将所有日期转换为时间戳类型来计算
# 3.5 方式三:使用pd.to_datetime()函数来转换所有日期为时间戳类型(timestamps.Timestam)来计算
df["date1"] = df["date1"].map(lambda x: datetime.strptime(x, "%Y.%m.%d"))
# 输入日期,并计算之间的日期差值
login = "2021.10.15"
df["login"] = datetime.strptime(login, "%Y.%m.%d").date()
df["time"] = pd.to_datetime(df["login"]) - pd.to_datetime(df["date1"])
df
结论:问题已经解决,没有再报错!
温馨提示:
日期计算后的数据是不能直接使用的(xxx days),需要提取时间差值并转换为数字类型
# 将计算之后的时间差值提取出来的代码:
df["time"] = df["time"].astype("str").map(lambda x: x.split())
df["time"] = df["time"].str[0].astype(int)
df