【问题标题】:Reshaping groupby dataframe to fixed dimensions将 groupby 数据框重塑为固定尺寸
【发布时间】:2026-01-30 23:10:01
【问题描述】:

我有带有以下数据的数据框 df。

A    B    C    D
1    1    3    1
1    2    9    8
1    3    3    9
2    1    2    9
2    2    1    4
2    3    9    5
2    4    6    4
3    1    4    1
3    2    0    4
4    1    2    6
5    1    2    4
5    2    8    3

grp = df.groupby('A')

接下来,我想让所有分组的数据帧 df 组在 A 列上具有相同的行数。截断多余的行或填充 0 行。对于上述数据,我想让所有组都有 3 行。我需要以下结果。

A    B    C    D
1    1    3    1
1    2    9    8
1    3    3    9
2    1    2    9
2    2    1    4
2    3    9    5
3    1    4    1
3    2    0    4
3    0    0    0
4    1    2    6
4    0    0    0
4    0    0    0
5    1    2    4
5    2    8    3
5    0    0    0

同样,我可能想在多个列上进行分组,例如 grp = df.groupby(['A','B'])

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    GroupBy.cumcount 用于计数器列,DataFrame.reindex by MultiIndex.from_product

    df['g'] = df.groupby('A').cumcount()
    mux = pd.MultiIndex.from_product([df['A'].unique(), range(3)], names=('A','g'))
    
    df = (df.set_index(['A','g'])
            .reindex(mux, fill_value=0)
            .reset_index(level=1, drop=True)
            .reset_index())
    print (df)
        A  B  C  D
    0   1  1  3  1
    1   1  2  9  8
    2   1  3  3  9
    3   2  1  2  9
    4   2  2  1  4
    5   2  3  9  5
    6   3  1  4  1
    7   3  2  0  4
    8   3  0  0  0
    9   4  1  2  6
    10  4  0  0  0
    11  4  0  0  0
    12  5  1  2  4
    13  5  2  8  3
    14  5  0  0  0
    

    另一个使用DataFrame.merge 的解决方案,带有左连接助手DataFrame

    from  itertools import product
    
    df['g'] = df.groupby('A').cumcount()
    df1 = pd.DataFrame(list(product(df['A'].unique(), range(3))), columns=['A','g'])
    
    df = df1.merge(df, how='left').fillna(0).astype(int).drop('g', axis=1)
    print (df)
        A  B  C  D
    0   1  1  3  1
    1   1  2  9  8
    2   1  3  3  9
    3   2  1  2  9
    4   2  2  1  4
    5   2  3  9  5
    6   3  1  4  1
    7   3  2  0  4
    8   3  0  0  0
    9   4  1  2  6
    10  4  0  0  0
    11  4  0  0  0
    12  5  1  2  4
    13  5  2  8  3
    14  5  0  0  0
    

    编辑:

    df['g'] = df.groupby(['A','B']).cumcount()
    
    mux = pd.MultiIndex.from_product([df['A'].unique(), 
                                      df['B'].unique(), 
                                      range(3)], names=('A','B','g'))
    df = (df.set_index(['A','B','g'])
            .reindex(mux, fill_value=0)
            .reset_index(level=2, drop=True)
            .reset_index())
    print (df.head(10))
       A  B  C  D
    0  1  1  3  1
    1  1  1  0  0
    2  1  1  0  0
    3  1  2  9  8
    4  1  2  0  0
    5  1  2  0  0
    6  1  3  3  9
    7  1  3  0  0
    8  1  3  0  0
    9  1  4  0  0
    

    from  itertools import product
    
    df['g'] = df.groupby(['A','B']).cumcount()
    df1 = pd.DataFrame(list(product(df['A'].unique(),
                                    df['B'].unique(), 
                                    range(3))), columns=['A','B','g'])
    
    df = df1.merge(df, how='left').fillna(0).astype(int).drop('g', axis=1)
    

    【讨论】:

    • 如果我为 groupby 使用一列,它工作正常。如果我必须对多个列进行分组,例如,我应该在代码中做哪些更改。 dfg = df.groupby(['A','B'])
    • 他们不是带有键 (1,4) 的组。索引 9,10,11 处的行不应出现在结果中。
    • @AsifKhan - 解决方案 ID 过滤器首先由 df = df[df.groupby('A').cumcount() < 3]