根据两个条件从另一个数据帧为数据帧赋值



我正在尝试将 df2['values'] 中的列中的值分配给 df1['values'] 列的值。但是,只有在以下情况下才应分配值:

  1. df2["类别"] 等于 df1["类别"](行属于同一类别(
  2. df1["日期"] 位于 df2["date_range"] 中(特定类别的日期在特定范围内(

到目前为止,我有这段代码,它可以工作,但效率远非高,因为处理两个 dfs 需要两天时间(df1 大约有 700k 行(。

for i in df1.category.unique():
for j in df2.category.unique():
if i == j: # matching categories
for ia, ra in df1.loc[df1['category'] == i].iterrows():
for ib, rb in df2.loc[df2['category'] == j].iterrows():
if df1['date'][ia] in df2['date_range'][ib]:
df1.loc[ia, 'values'] = rb['values']
break

我读到在处理数据帧时应该尽量避免使用 for 循环。列表理解很棒,但是由于我还没有很多经验,所以我很难制定更复杂的代码。

如何更有效地迭代此问题?在迭代有条件的数据帧时,我应该考虑哪些重要的关键方面?

上面的代码倾向于跳过一些行或错误地分配它们,所以我需要在之后进行清理。最大的问题是,它真的很慢。

谢谢。

一些 df1 见解:

df1.head()
date                          category
0  2015-01-07                       f2
1  2015-01-26                       f2
2  2015-01-26                       f2
3  2015-04-08                       f2
4  2015-04-10                       f2

一些 df2 见解:

df2.date_range[0]
DatetimeIndex(['2011-11-02', '2011-11-03', '2011-11-04', '2011-11-05',
'2011-11-06', '2011-11-07', '2011-11-08', '2011-11-09',
'2011-11-10', '2011-11-11', '2011-11-12', '2011-11-13',
'2011-11-14', '2011-11-15', '2011-11-16', '2011-11-17',
'2011-11-18'],
dtype='datetime64[ns]', freq='D')

DF2 其他两列:

df2[['values','category']].head()
values             category
0            01                  f1
1            02                  f1
2           2.1                  f1
3           2.2                  f1
4            03                  f1

编辑:更正了错误的代码并从注释中添加了 OP 输入

好的,如果您想加入类似类别的数据帧,您可以merge它们:

import pandas as pd
df3 = df1.merge(df2, on = "category")

接下来,由于date是一个时间戳,而"date_range"实际上是从两列生成的,根据 OP 的评论,我们宁愿使用:

mask = (df3["startdate"] <= df3["date"]) & (df3["date"] <= df3["enddate"])
subset = df3.loc[mask]

现在我们回到df1并合并公共日期,同时保留所有值df1.这将为子集值创建NaN,其中子集值与早期合并中的df1不匹配。

因此,我们将df1["values"]设置了不NaN共同条目的位置,否则我们将它们保留。

common_dates = df1.merge(subset, on = "date", how= "left") # keeping df1 values
df1["values"] = np.where(common_dates["values_y"].notna(), 
common_dates["values_y"], df1["values"])

注意:如果多个df1["date"]与日期范围匹配,则必须删除一些值,否则重复会使解释混乱。

你可以完成第一点:

1. DF2["类别"]等于 DF1["类别"]

使用联接。

然后,您可以使用 for 循环来过滤合并数据帧内 df1[date] 中未考虑的 df2[date_range] 中的数据位置。不幸的是,我需要更多关于 df1[date] 和 df2[date_range] 内容的信息来编写完全可以做到这一点的代码。

最新更新