Pandas 在 groupby 列中用 NaN 填充组时删除单元格

Pandas deleting cells when filling groups with NaN in groupby column

我试图通过将已知值传播到同一组内的值来填充 DataFrame 中的空行。当分组的所有列都已满时,这似乎工作正常,但如果列中有空单元格,Pandas 将删除值。在提供的示例中,DataFrame 在索引 6 和 8 的“B”列中具有 NaN。在组上使用 ffillbfill 后,第 6 行和第 8 行中的数字已替换为 NaN。我该如何避免这种意外的副作用?

代码:

import pandas as pd
import numpy as np

df = pd.DataFrame({"A": [1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, 6],
                    "B": ['a', 'a', 'b', 'b', 'b', 'c', np.nan, 'd', 
                          np.nan, 'e', 'e', 'g', 'h', 'h'],
                    "C": [5.0, np.nan, 4.0, 4.0, np.nan, 9.0, np.nan, 
                          np.nan, 9.0, 8.0, np.nan, 2.0, np.nan, 3.0],
                    "D": [1.0, 1.0, np.nan, 2.0, np.nan, np.nan, np.nan, 
                          np.nan, 3.0, 2.0, np.nan, 9.0, np.nan, 3.0],
                    "E": [np.nan, 6.0, np.nan, 3.0, np.nan, np.nan, 7.0, 
                          np.nan, 7.0, 2.0, np.nan, np.nan, np.nan, 0.0]})

cols_to_groupby = ["A", "B"]
cols_to_fill = ["C", "D", "E"]

original_indxs = df.index
df[cols_to_fill] = (
    df.sort_values(cols_to_groupby)[cols_to_fill + cols_to_groupby]
    .groupby(cols_to_groupby)
    .transform(lambda x: x.ffill().bfill())
)

示例数据集:

    A    B    C    D    E
0   1    a  5.0  1.0  NaN
1   1    a  NaN  1.0  6.0
2   2    b  4.0  NaN  NaN
3   2    b  4.0  2.0  3.0
4   2    b  NaN  NaN  NaN
5   3    c  9.0  NaN  NaN
6   3  NaN  NaN  NaN  7.0
7   3    d  NaN  NaN  NaN
8   3  NaN  9.0  3.0  7.0
9   4    e  8.0  2.0  2.0
10  4    e  NaN  NaN  NaN
11  5    g  2.0  9.0  NaN
12  6    h  NaN  NaN  NaN
13  6    h  3.0  3.0  0.0

预期结果:

    A    B    C    D    E
0   1    a  5.0  1.0  6.0
1   1    a  5.0  1.0  6.0
2   2    b  4.0  2.0  3.0
3   2    b  4.0  2.0  3.0
4   2    b  4.0  2.0  3.0
5   3    c  9.0  NaN  NaN
6   3  NaN  NaN  NaN  7.0
7   3    d  NaN  NaN  NaN
8   3  NaN  9.0  3.0  7.0
9   4    e  8.0  2.0  2.0
10  4    e  8.0  2.0  2.0
11  5    g  2.0  9.0  NaN
12  6    h  3.0  3.0  0.0
13  6    h  3.0  3.0  0.0

实际结果:

    A    B    C    D    E
0   1    a  5.0  1.0  6.0
1   1    a  5.0  1.0  6.0
2   2    b  4.0  2.0  3.0
3   2    b  4.0  2.0  3.0
4   2    b  4.0  2.0  3.0
5   3    c  9.0  NaN  NaN
6   3  NaN  NaN  NaN  NaN
7   3    d  NaN  NaN  NaN
8   3  NaN  NaN  NaN  NaN
9   4    e  8.0  2.0  2.0
10  4    e  8.0  2.0  2.0
11  5    g  2.0  9.0  NaN
12  6    h  3.0  3.0  0.0
13  6    h  3.0  3.0  0.0

默认情况下groupby会忽略组键列包含NaN值的行,所以你不能依赖索引对齐(df[cols_to_fill] = ...)来更新我们这里的dataframe必须明确 update 原始数据框与 groupby

的结果
cols = df.groupby(cols_to_groupby)[cols_to_fill].apply(lambda x: x.ffill().bfill())
df.update(cols)

    A    B    C    D    E
0   1    a  5.0  1.0  6.0
1   1    a  5.0  1.0  6.0
2   2    b  4.0  2.0  3.0
3   2    b  4.0  2.0  3.0
4   2    b  4.0  2.0  3.0
5   3    c  9.0  NaN  NaN
6   3  NaN  NaN  NaN  7.0
7   3    d  NaN  NaN  NaN
8   3  NaN  9.0  3.0  7.0
9   4    e  8.0  2.0  2.0
10  4    e  8.0  2.0  2.0
11  5    g  2.0  9.0  NaN
12  6    h  3.0  3.0  0.0
13  6    h  3.0  3.0  0.0