我正在尝试在 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
。