将groupby数据框重塑为固定尺寸

时间:2019-04-23 05:43:17

标签: python pandas numpy

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

接下来,我要使在列A上分组的所有数据帧df组具有相同的行数。截断多余的行或填充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'])

1 个答案:

答案 0 :(得分:2)

GroupBy.cumcount中的DataFrame.reindex用于计数器列,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)