我正在通过试图在索引中查找值的数据集进行循环。如果该值不在(多级)索引中,则我采用默认值:
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)值,因为我知道这将返回一些东西
答案 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)。