首页 > 解决方案 > 将 groupby 数据框重塑为固定尺寸

问题描述

我有带有以下数据的数据框 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'])

标签: pythonpandasnumpy

解决方案


用于带有byGroupBy.cumcount的计数器列:DataFrame.reindexMultiIndex.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)

推荐阅读