根据两个条件,将值分配给另一个数据框中的数据框

时间:2020-01-04 13:37:23

标签: python pandas loops dataframe

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

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

到目前为止,我拥有此代码,该代码可以工作,但是效率不高,因为处理两个df(df1大约有70万行)需要花两天的时间。

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

1 个答案:

答案 0 :(得分:0)

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

好的,因此,如果要加入类似类别的数据框,可以merge进行使用:

import pandas as pd

df3 = df1.merge(df2, on = "category")

接下来,由于date是一个时间戳,并且根据OP的注释,“ date_range”实际上是从两列生成的,因此我们使用:

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"])

N.B:如果与日期范围匹配的多个df1["date"],则必须删除一些值,否则重复的内容会弄乱解释。