熊猫-基于groupby中其他列设置列的最佳方法

时间:2018-08-01 20:03:36

标签: python pandas pandas-groupby

我很难想象用另一种方式在熊猫中做到这一点。我的方式“有效”,但速度非常慢。在高级别上,我想这样做:

  1. id分组数据,找到a的中位数。
  2. 找出a的每个值与其组中位数之间的差值
  3. 在一组中位数中找到最大值
  4. 然后,在组中,如果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,或者可以采用更好的方法)?

编辑:正如您可能已经注意到的,如果到目前为止,这只是我尝试以特定方式填充缺失值的原因。如果有一种更简单的方法来完成整个操作,那么我很烦:)

2 个答案:

答案 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'])