DatetimeSubtraction#
通常,我们的数据集中会有日期时间变量,我们希望确定它们之间的时间差。例如,如果我们处理金融数据,我们可能会有变量 贷款申请日期,记录客户申请贷款的日期和时间,以及变量 出生日期,记录客户的出生日期。通过这两个变量,我们想要推断出 客户在申请时的年龄。为了做到这一点,我们可以计算 date_of_loan_application
和 date_of_birth
之间的年份差,并将其捕获到一个新变量中。
在另一个例子中,如果我们试图预测房屋的价格,并且我们有关于房屋建造年份的信息,我们可以推断出房屋在销售时的年龄。通常,较老的房屋价格较低。为了计算房屋的年龄,我们只需计算销售日期与建造日期之间的年份差。
Python 程序提供了许多选项来操作 datetime 对象,例如 datetime 模块。由于您很可能使用 Pandas 数据框,我们将重点介绍 pandas,然后介绍如何使用 Feature-engine 自动化该过程。
使用 pandas 减去 datetime 特征#
在Python中,我们可以使用pandas减去datetime对象。要在pandas中处理datetime变量,我们需要确保时间戳(可以以各种格式表示,如字符串(str)、对象("O"
)或datetime)被转换为datetime。如果没有,我们可以通过执行 pd.to_datetime(df[variable_of_interest])
将字符串转换为datetime对象。
让我们创建一个包含2个日期时间变量的玩具数据框,用于一个简短的演示:
import numpy as np
import pandas as pd
data = pd.DataFrame({
"date1": pd.date_range("2019-03-05", periods=5, freq="D"),
"date2": pd.date_range("2018-03-05", periods=5, freq="W")})
print(data)
这是我们创建的数据,包含两个日期时间变量:
date1 date2
0 2019-03-05 2018-03-11
1 2019-03-06 2018-03-18
2 2019-03-07 2018-03-25
3 2019-03-08 2018-04-01
4 2019-03-09 2018-04-08
现在,我们可以利用 pandas 的减法运算符将 date2
从 date1
中减去,并将差值捕获到一个新的变量中:
data["diff"] = data["date1"].sub(data["date2"])
print(data)
表示天数差异的新变量位于数据框的右侧:
date1 date2 diff
0 2019-03-05 2018-03-11 359 days
1 2019-03-06 2018-03-18 353 days
2 2019-03-07 2018-03-25 347 days
3 2019-03-08 2018-04-01 341 days
4 2019-03-09 2018-04-08 335 days
如果我们希望时间单位不是天,我们可以使用 numpy 的 timedelta。以下示例展示了如何使用此语法:
data["diff"] = data["date1"].sub(data["date2"], axis=0).div(
np.timedelta64(1, "Y").astype("timedelta64[ns]"))
print(data)
我们现在看到新的变量现在表示年份的差异,在数据框的右侧:
date1 date2 diff
0 2019-03-05 2018-03-11 0.982909
1 2019-03-06 2018-03-18 0.966481
2 2019-03-07 2018-03-25 0.950054
3 2019-03-08 2018-04-01 0.933626
4 2019-03-09 2018-04-08 0.917199
如果你想减去不同的 datetime 变量,你必须为每次减法编写代码行。幸运的是,我们可以使用 DatetimeSubstraction()
来自动化这个过程。
使用 Feature-engine 进行日期时间减法#
DatetimeSubstraction()
自动从彼此中减去多个日期和时间特征。你只需要在 variables
参数中指示减法操作右侧的特征,并在 reference
参数中指示左侧的特征。你还可以通过 output_unit
参数更改输出单位。
DatetimeSubstraction()
适用于 dtype
为 datetime 的变量,以及对象类型和分类变量,前提是它们可以解析为 datetime 格式。这将在转换器的后台完成。
继续前面的例子,以下是我们如何使用 DatetimeSubstraction()
获取天数差异:
import pandas as pd
from feature_engine.datetime import DatetimeSubtraction
data = pd.DataFrame({
"date1": pd.date_range("2019-03-05", periods=5, freq="D"),
"date2": pd.date_range("2018-03-05", periods=5, freq="W")})
dtf = DatetimeSubtraction(
variables="date1",
reference="date2",
output_unit="Y")
data = dtf.fit_transform(data)
print(data)
通过 transform()
,DatetimeSubstraction()
返回一个新的数据框,包含原始变量以及带有时间差的新变量:
date1 date2 date1_sub_date2
0 2019-03-05 2018-03-11 0.982909
1 2019-03-06 2018-03-18 0.966481
2 2019-03-07 2018-03-25 0.950054
3 2019-03-08 2018-04-01 0.933626
4 2019-03-09 2018-04-08 0.917199
计算后丢弃原始变量#
我们可以在计算后选择删除原始的日期时间变量:
import pandas as pd
from feature_engine.datetime import DatetimeSubtraction
data = pd.DataFrame({
"date1": pd.date_range("2019-03-05", periods=5, freq="D"),
"date2": pd.date_range("2018-03-05", periods=5, freq="W")})
dtf = DatetimeSubtraction(
variables="date1",
reference="date2",
output_unit="M",
drop_original=True
)
data = dtf.fit_transform(data)
print(data)
在这种情况下,生成的数据框仅包含两个原始变量之间的时间差:
date1_sub_date2
0 11.794903
1 11.597774
2 11.400645
3 11.203515
4 11.006386
同时减去多个变量#
我们可以同时执行多次减法。在这个例子中,我们将新的日期时间变量作为字符串添加到玩具数据框中。这个想法是为了展示 DatetimeSubstraction()
将在幕后将这些字符串转换为日期时间以执行减法操作。
import pandas as pd
from feature_engine.datetime import DatetimeSubtraction
data = pd.DataFrame({
"date1" : ["2022-09-01", "2022-10-01", "2022-12-01"],
"date2" : ["2022-09-15", "2022-10-15", "2022-12-15"],
"date3" : ["2022-08-01", "2022-09-01", "2022-11-01"],
"date4" : ["2022-08-15", "2022-09-15", "2022-11-15"],
})
dtf = DatetimeSubtraction(variables=["date1", "date2"], reference=["date3", "date4"])
data = dtf.fit_transform(data)
print(data)
生成的数据框包含原始变量以及表示日期对象之间时间差的新变量。
date1 date2 date3 date4 date1_sub_date3 \
0 2022-09-01 2022-09-15 2022-08-01 2022-08-15 31.0
1 2022-10-01 2022-10-15 2022-09-01 2022-09-15 30.0
2 2022-12-01 2022-12-15 2022-11-01 2022-11-15 30.0
date2_sub_date3 date1_sub_date4 date2_sub_date4
0 45.0 17.0 31.0
1 44.0 16.0 30.0
2 44.0 16.0 30.0
处理缺失值#
默认情况下,DatetimeSubstraction()
如果在传递给 fit()
或 transform()
方法的数据框中,减法变量包含 NA,则会引发错误。我们可以通过将参数 missing_values
设置为 "ignore"
来覆盖此行为,并允许在包含 nan 的变量之间进行计算。以下是一个代码示例:
import numpy as np
import pandas as pd
from feature_engine.datetime import DatetimeSubtraction
data = pd.DataFrame({
"date1" : ["2022-09-01", "2022-10-01", "2022-12-01"],
"date2" : ["2022-09-15", np.nan, "2022-12-15"],
"date3" : ["2022-08-01", "2022-09-01", "2022-11-01"],
"date4" : ["2022-08-15", "2022-09-15", np.nan],
})
dtf = DatetimeSubtraction(
variables=["date1", "date2"],
reference=["date3", "date4"],
missing_values="ignore")
data = dtf.fit_transform(data)
print(data)
当任何变量包含 NAN 时,带有时间差的新特征也将显示 NAN:
date1 date2 date3 date4 date1_sub_date3 \
0 2022-09-01 2022-09-15 2022-08-01 2022-08-15 31.0
1 2022-10-01 NaN 2022-09-01 2022-09-15 30.0
2 2022-12-01 2022-12-15 2022-11-01 NaN 30.0
date2_sub_date3 date1_sub_date4 date2_sub_date4
0 45.0 17.0 31.0
1 NaN 16.0 NaN
2 44.0 NaN NaN
处理不同的时区#
如果我们有来自不同时区的时间戳或变量,我们仍然可以通过首先将所有时间戳设置为通用中央时区,使用 DatetimeSubstraction()
进行减法操作。以下是一个代码示例,我们返回以微秒为单位的时间差:
import pandas as pd
from feature_engine.datetime import DatetimeSubtraction
data = pd.DataFrame({
"date1": ['12:34:45+3', '23:01:02-6', '11:59:21-8', '08:44:23Z'],
"date2": ['09:34:45+1', '23:01:02-6+1', '11:59:21-8-2', '08:44:23+3']
})
dfts = DatetimeSubtraction(
variables="date1",
reference="date2",
utc=True,
output_unit="ms",
format="mixed"
)
new = dfts.fit_transform(data)
print(new)
我们看到结果数据框中以微秒为单位的时间差:
date1 date2 date1_sub_date2
0 12:34:45+3 09:34:45+1 3600000.0
1 23:01:02-6 23:01:02-6+1 25200000.0
2 11:59:21-8 11:59:21-8-2 21600000.0
3 08:44:23Z 08:44:23+3 10800000.0
将任意名称添加到新变量#
通常,我们只想计算几个时间差。在这种情况下,我们可能也希望为新变量分配特定的名称。在这个代码示例中,我们就是这样做的:
import pandas as pd
from feature_engine.datetime import DatetimeSubtraction
data = pd.DataFrame({
"date1": pd.date_range("2019-03-05", periods=5, freq="D"),
"date2": pd.date_range("2018-03-05", periods=5, freq="W")})
dtf = DatetimeSubtraction(
variables="date1",
reference="date2",
new_variables_names=["my_new_var"]
)
data = dtf.fit_transform(data)
print(data)
在生成的数据框中,我们看到时间差异被捕获在一个名为 my_new_var
的变量中:
date1 date2 my_new_var
0 2019-03-05 2018-03-11 359.0
1 2019-03-06 2018-03-18 353.0
2 2019-03-07 2018-03-25 347.0
3 2019-03-08 2018-04-01 341.0
4 2019-03-09 2018-04-08 335.0
我们应该注意传递一个包含尽可能多新变量名称的变量列表。将要创建的变量数量是通过将参数 variables
中的变量数量乘以参数 reference
中的变量数量得到的。
get_feature_names_out()#
最后,我们可以提取转换后的数据框的名称,以与 Scikit-learn 管道兼容:
import pandas as pd
from feature_engine.datetime import DatetimeSubtraction
data = pd.DataFrame({
"date1" : ["2022-09-01", "2022-10-01", "2022-12-01"],
"date2" : ["2022-09-15", "2022-10-15", "2022-12-15"],
"date3" : ["2022-08-01", "2022-09-01", "2022-11-01"],
"date4" : ["2022-08-15", "2022-09-15", "2022-11-15"],
})
dtf = DatetimeSubtraction(variables=["date1", "date2"], reference=["date3", "date4"])
dtf.fit(data)
dtf.get_feature_names_out()
以下是应用 transform()
方法后,任何数据框中将出现的变量名称:
['date1',
'date2',
'date3',
'date4',
'date1_sub_date3',
'date2_sub_date3',
'date1_sub_date4',
'date2_sub_date4']
结合提取和减去日期时间特征#
我们还可以通过减去日期时间变量来结合从日期时间特征创建数值变量与创建新特征:
import pandas as pd
from sklearn.pipeline import Pipeline
from feature_engine.datetime import DatetimeFeatures, DatetimeSubtraction
data = pd.DataFrame({
"date1" : ["2022-09-01", "2022-10-01", "2022-12-01"],
"date2" : ["2022-09-15", "2022-10-15", "2022-12-15"],
"date3" : ["2022-08-01", "2022-09-01", "2022-11-01"],
"date4" : ["2022-08-15", "2022-09-15", "2022-11-15"],
})
dtf = DatetimeFeatures(variables=["date1", "date2"], drop_original=False)
dts = DatetimeSubtraction(
variables=["date1", "date2"],
reference=["date3", "date4"],
drop_original=True,
)
pipe = Pipeline([
("features", dtf),("subtraction", dts)
])
data = pipe.fit_transform(data)
print(data)
在以下输出中,我们看到包含从不同日期时间变量中提取的特征的新数据框,随后是捕获时间差异创建的特征:
date1_month date1_year date1_day_of_week date1_day_of_month date1_hour \
0 9 2022 3 1 0
1 10 2022 5 1 0
2 12 2022 3 1 0
date1_minute date1_second date2_month date2_year date2_day_of_week \
0 0 0 9 2022 3
1 0 0 10 2022 5
2 0 0 12 2022 3
date2_day_of_month date2_hour date2_minute date2_second \
0 15 0 0 0
1 15 0 0 0
2 15 0 0 0
date1_sub_date3 date2_sub_date3 date1_sub_date4 date2_sub_date4
0 31.0 45.0 17.0 31.0
1 30.0 44.0 16.0 30.0
2 30.0 44.0 16.0 30.0
其他资源#
有关如何创建和使用来自 datetime 列的功能的教程,请查看以下课程:
或者阅读我们的书:
我们的书籍和课程都适合初学者和更高级的数据科学家。通过购买它们,您正在支持 Feature-engine 的主要开发者 Sole。