代码优化 - 按月比较两个日期时间列,创建新列的速度太慢



我正在尝试在 Pandas 数据帧中创建一个新列。如果数据帧中的其他两个日期列共享同一月份,则此新列的值应为 1,否则为 0。此外,我需要检查 id 是否与我之前保存在另一个地方的其他 id 列表匹配,并仅用 1 标记这些 id。我有一些代码,但它毫无用处,因为我正在处理近十亿行。

my_list_of_ids = df[df.bool_column == 1].id.values
def my_func(date1, date2):
for id_ in df.id:
if id_ in my_list_of_ids:
if date1.month == date2.month:
my_var = 1
else:
my_var = 0
else:
my_var = 0
return my_var
df["new_column"] = df.progress_apply(lambda x: my_func(x['date1'], x['date2']), axis=1)

已经等了30分钟,仍然是0%。任何帮助,不胜感激。

更新(添加示例(:

id   |    date1   |    date2     | bool_column |  new_column |
id1    2019-02-13    2019-04-11     1                  0
id1    2019-03-15    2019-04-11     0                  0
id1    2019-04-23    2019-04-11     0                  1 
id2    2019-08-22    2019-08-11     1                  1
id2      ....
id3    2019-09-01    2019-09-30     1                  1
.
.
.

我需要做的是将 1 的 id 保存在我的bool_column中,然后我循环访问数据帧中的所有 id,并检查它们是否在先前创建的列表中 (= 1(。然后我想比较 date1 和 date2 列的月份和年份,如果它们相同,请创建一个值为 1 的new_column,否则为 0。

熊猫这样做的方法是

mask = ((df['date1'].month == df['date2'].month) & (df['id'].isin(my_list_of_ids)))
df['new_column'] = mask.replace({False: 0, True: 1})

由于您有一个大型数据集,这将需要时间,但应该比使用 apply 更快

处理月份匹配的最佳方法是在熊猫中使用矢量化并执行以下操作:

new_column = (df.date1.dt.month == df.date2.dt.month).astype(int)

也就是说,避免在DataFrame上使用apply()(这可能是迭代的(,并利用基础numpy矢量化。此类功能的网关几乎总是位于Series函数和属性系列中,例如用于日期的dt系列、用于字符串str系列等。

幸运的是,您已经预先计算了bool_column中的id_list成员资格,因此要添加成员资格作为条件,只需执行以下操作:

new_column = ((df.date1.dt.month == df.date2.dt.month) & df.bool_column).astype(int)

同样,两个Series&利用了矢量化。你一直呆在布尔空间里直到最后,然后用astype(int)投射到int。回顾您的代码,我突然想到,对您的id_list进行迭代检查可能是这里真正的性能影响,甚至比DataFrame.apply()更严重。无论您做什么,都要避免不惜一切代价在每一行迭代您的id_list,因为您已经有一个向量表示bool_column中的成员资格。

顺便说一下,我相信您的示例数据中存在一个小错误,第三行的new_column值应该是0,因为您的bool_column值是0

最新更新