我很难想象用另一种方式在熊猫中做到这一点。我的方式“有效”,但速度非常慢。在高级别上,我想这样做:
id
分组数据,找到a
的中位数。a
的每个值与其组中位数之间的差值a
丢失/不正确,则如果a
中的值小于公差(例如1),则将step 3
覆盖/设置为中位数。 这是我的操作方式:
假设数据帧为df:
df = pd.DataFrame({'id': [1,1,2,2,3], 'a': [1, np.nan, 3, 1, 2], 'b': [np.nan, 6, 5, np.nan, 4], 'c': [4, 1, 2, 3, 3]})
id a b c
0 1 1.0 NaN 4
1 1 NaN 6.0 1
2 2 3.0 5.0 2
3 2 1.0 NaN 3
4 3 2.0 4.0 3
步骤1:
df['median'] = df.groupby(['id'])['a'].transform('median')
步骤2:
df['diff'] = abs(df['a'] - df['median'])
步骤3:
df['diff'] = df.groupby(['id'])['diff'].transform('max')
第4步:
for key, g in df.groupby(['id']):
index = (df.id == key) & (df['diff'] < 1.0) & (df.a.isna())
if not df[index].empty:
df.loc[index, 'a'] = g['median']
我对步骤1-3是正确的并且以有效的方式完成(并希望在偶代大熊猫中)充满信心。第4步我不喜欢,我很确定这是瓶颈,而且这似乎是错误的方法。我想不通另一种方法。
关于改进第4步的任何建议(如果不正确,则建议1-3,或者可以采用更好的方法)?
编辑:正如您可能已经注意到的,如果到目前为止,这只是我尝试以特定方式填充缺失值的原因。如果有一种更简单的方法来完成整个操作,那么我很烦:)
答案 0 :(得分:1)
由于中值列已经与'a'
对齐,所以我认为根本不需要循环,甚至不需要循环groupby
。
df['a'] = df['median'].where(df['a'].isna() & (df['diff'] < 1), df['a'])
这将在适当的地方采用中位数,否则只需使用'a'
。
答案 1 :(得分:1)
还要考虑numpy的where
,以用于整个系列/数组的条件逻辑。用以下内容替换循环:
df['a'] = np.where((df['a'].isna()) & (df['diff'] < 1), df['median'], df['a'])