折叠 Pandas 行以消除 NaN 条目

Collapse Pandas rows to elliminate NaN entries

让我们考虑以下DataFrame

Name A B C D
tom 10.0 NaN NaN NaN
tom NaN 15.0 NaN NaN
tom NaN NaN 20.0 NaN
tom NaN NaN NaN 25.0
tom 30.0 NaN NaN NaN
tom NaN NaN NaN 40.0
john 1.0 NaN NaN NaN
john NaN 2.0 NaN NaN
john NaN NaN 3.0 NaN
john NaN NaN NaN 4.0
john 5.0 NaN NaN NaN
john NaN 6.0 NaN NaN
john NaN NaN 7.0 NaN
john NaN NaN NaN 8.0

我想折叠它以限制 DataFrame 中 NaN 值的数量 - 可以是顺序的,即如果可能的话合并相邻的行,但我只关心列的值 A-D对应崩后同一个Name

我的完美结果是

Name A B C D
tom 10.0 15.0 20.0 25.0
tom 30.0 NaN NaN 40.0
john 1.0 2.0 3.0 4.0
john 5.0 6.0 7.0 8.0

据我了解,Pandas groupby('Name') 不会成功,因为它会为每个名称留下一个条目。

如果这有任何帮助,我会使用字典来创建数据框。字典看起来像这样:

{
    "a": {
        "tom": [10.0, 30.0],
        "john": [1.0, 5.0]
    },
    "b": {
        "tom": [15.0],
        "john": [2.0, 6.0]
    },
    .....
}

所以,基本上,我取字典中的每个数字,然后只用这个数字创建一行,然后合并所有行。

给定这样的字典,是否有一种简单的方法来折叠生成的 DataFrame 或构建更紧凑的 DataFrame

您可以 .groupby + .transform(将值“向上移动”)。然后删除包含所有 NaN 值的行:

print(
    df.set_index("Name")
    .groupby(level=0)
    .transform(lambda x: sorted(x, key=lambda k: pd.isna(k)))
    .dropna(axis=0, how="all")
    .reset_index()
)

打印:

   Name     A     B     C     D
0   tom  10.0  15.0  20.0  25.0
1   tom  30.0   NaN   NaN  40.0
2  john   1.0   2.0   3.0   4.0
3  john   5.0   6.0   7.0   8.0