在pandas中矢量化索引查找

时间:2018-03-30 17:37:39

标签: pandas numpy vectorization

我正在通过试图在索引中查找值的数据集进行循环。如果该值不在(多级)索引中,则我采用默认值:

for i,row in df.iterrows():
    if i in avg_days.index:
        df.at[i,'avg_days_to_n'] = round(avg_days.xs(i,axis=0)[1],0)
    else:
        df.at[i,'avg_days_to_n'] = round(avg_days.xs((i[0],i[1]),level (0,1),drop_level=False).avg_days_between_n.mean(),0)

有没有办法对此进行矢量化?

以下是avg_days数据框的样子:

                            avg_n
state   project_type    cat 
FL      R               Hur 33
CA      C               EE  43

这是df的样子:

                            id
state   project_type    cat 
FL      R               Hur abc-1
CA      C               EE  def-2

因此,对于df中的每一行,如果索引state-project_type-cat在avg_days中具有索引匹配,则返回avg_n值。

如果没有,我“向上移动”索引并获取状态项目类型(而不是cat)值,因为我知道这将返回一些东西

1 个答案:

答案 0 :(得分:1)

第一部分,同时匹配所有3个索引,可以通过pandas中实现的merge函数轻松实现。为了维护df中找到的所有索引,即使它们不在avg_days中,how参数也必须设置为left

merged_df = pd.merge(df,avg_days,right_index=True,left_index=True,how='left')

第二部分比那更棘手。合并之后,avg_n数据框的merged_df值中将存在没有任何值的索引,这些索引必须设置为前{2}的avg_n均值索引。

可以使用groupby函数计算平均值,然后可以检查需要更正的列表的索引,检查NaN

days_grouped = np.around(avg_days.groupby(['state','project_type']).mean())
nan_mask = ~np.isfinite(merged_df['avg_n'])
indexes2correct = [(s,p) for s,p,c in merged_df[nan_mask].index.values]

最后,可以使用NaN中的值更新包含days_gruped的行:

merged_df.loc[nan_mask,'avg_n'] = days_grouped.loc[indexes2correct]['avg_n'].values 

注意:我将获得的结果与问题中显示的代码和这种矢量化方式进行了比较,并且应该考虑一些差异:

  • 此处,只有平均值被舍入,avg_days['avg_n']中的值假定为整数。
  • 使用numpy.round而不是内置round进行舍入,在某些情况下,舍入到不同的值(有关详细信息,请参阅this other question)。