一次使用多个 fillna 策略的 groupby (pandas)

groupby with multiple fillna strategies at once (pandas)

如何按一列分组,然后在每个组内同时对其他列应用多个 fillna 策略?多重含义:

  1. 如果组中第一个,用零替换,然后填充直到到达第一个数据点
  2. 尾随的 NaN 被填充
  3. 对于数据点之间的所有 NaN,bfill
  4. 如果全是 NaN,就不要管组

基本上,我有以下数据框:

    A    B     C
0   A  NaN   NaN
1   A  NaN   NaN
2   A  1.0  10.0
3   A  NaN   NaN
4   B  NaN   NaN
5   B  2.0  20.0
6   B  NaN  20.0
7   B  NaN   NaN
8   C  NaN   NaN
9   C  NaN   NaN
10  C  NaN   NaN
11  C  NaN  30.0

我希望它变成:

    A    B     C
0   A    0     0
1   A    0     0
2   A  1.0  10.0
3   A  1.0  10.0
4   B    0     0
5   B  2.0  20.0
6   B  2.0  20.0
7   B  2.0  20.0
8   C  NaN     0
9   C  NaN     0
10  C  NaN     0
11  C  NaN  30.0

我尝试使用 df.groupby('A').nth(1) 获取第一个元素并有条件地继续,但是 groupby 创建的新索引不是原始索引(即 0,4,8),无论如何我是否通过 .reset_index() 选项。

数据框重建代码:


df = pd.DataFrame({'A' : ["A", "A", "A", "A",
                          "B", "B", "B", "B","C", "C", "C", "C"],
                   'B' : [np.nan, np.nan, 1, np.nan,
                          np.nan, 2, np.nan, np.nan,
                          np.nan, np.nan, np.nan, np.nan],
                   'C' : [np.nan, np.nan, 10, np.nan,
                          np.nan, 20, 20, np.nan,
                          np.nan, np.nan, np.nan, 30]})

一个可能的想法是在 A 上使用 DataFrame.groupby,然后使用自定义转换器函数:

def fx(s):
    if s.isna().all():
        return s
    elif pd.isna(s.iloc[0]):
        s.iloc[0] = 0
        s = s.ffill().bfill()
    return s

df[['B', 'C']] = df.groupby('A')[['B', 'C']].transform(fx)

# print(df)
    A    B     C
0   A  0.0   0.0
1   A  0.0   0.0
2   A  1.0  10.0
3   A  1.0  10.0
4   B  0.0   0.0
5   B  2.0  20.0
6   B  2.0  20.0
7   B  2.0  20.0
8   C  NaN   0.0
9   C  NaN   0.0
10  C  NaN   0.0
11  C  NaN  30.0