Pandas Dataframe根据一列中的惟一值使用mean-based重复行,使每个惟一值具有相同的行数

  • 本文关键字:Dataframe 一列 mean-based Pandas python pandas
  • 更新时间 :
  • 英文 :


我有一个像下面这样的数据框架:

import numpy as np
import pandas as pd
df = pd.DataFrame({"Column1":
["A", "A", "A", "A", "B", "B", "B", "C", "C", "D"],
"Column2": [24., 25, 21., 33, 26, 24., 25, 21., 33, 26],
"Column3": [0.2, 0.3, 0.4, 0.5, 0.6, 0.2, 0.3, 0.4, 0.5, 0.6]})
Column1  Column2  Column3
0      A    24.0     0.2
1      A    25.0     0.3
2      A    21.0     0.4
3      A    33.0     0.5
4      B    26.0     0.6
5      B    24.0     0.2
6      B    25.0     0.3
7      C    21.0     0.4
8      C    33.0     0.5
9      D    26.0     0.6

这里有4行对应A, 3行对应B, 2行对应C, 1行对应d

我怎么能添加行B, C和D有相同的数字与A有4行使用他们的平均值?

例如,对于column2, B的平均值是(26+25+24)/3 = 25,对于column3, B的平均值是(0.6+0.2+0.3)/3 = 0.37

所以我添加了一行b25 0.37

对于C,只有2行,第2列和第3列的平均值分别为27和0.45

所以我添加了两行c27 0.45

对于D只有一行,所以我们用相同的值添加三行

目标是:

Column1  Column2  Column3
0      A    24.0     0.2
1      A    25.0     0.3
2      A    21.0     0.4
3      A    33.0     0.5
4      B    26.0     0.6
5      B    24.0     0.2
6      B    25.0     0.3
7      B    25.0     0.37
8      C    21.0     0.4
9      C    33.0     0.5
10     C    27.0     0.45
11     C    27.0     0.45
12     D    26.0     0.6
13     D    26.0     0.6
14     D    26.0     0.6
15     D    26.0     0.6

解决方案

g = df.groupby('Column1')
avg, s = g.mean(), g.size()
rows = avg.loc[avg.index.repeat(s.max() - s)]
pd.concat([df, rows.reset_index()]).sort_values('Column1')

解释:

计算各组meansize

>>> avg
Column2    Column3
Column1                  
A        25.75  0.350000
B        25.00  0.366667
C        27.00  0.450000
D        26.00  0.600000
>>> s
Column1
A    4
B    3
C    2
D    1
dtype: int64

Repeatavg数据帧的行数N次,其中N由最大组大小减去每个组的大小获得

>>> rows
Column2    Column3
Column1                  
B         25.0  0.366667
C         27.0  0.450000
C         27.0  0.450000
D         26.0  0.600000
D         26.0  0.600000
D         26.0  0.600000

Concat与抽样rows的原始数据帧,以获得具有平衡组分布的数据帧

Column1  Column2    Column3
0      A    24.0  0.200000
1      A    25.0  0.300000
2      A    21.0  0.400000
3      A    33.0  0.500000
4      B    26.0  0.600000
5      B    24.0  0.200000
6      B    25.0  0.300000
0      B    25.0  0.366667
7      C    21.0  0.400000
8      C    33.0  0.500000
1      C    27.0  0.450000
2      C    27.0  0.450000
9      D    26.0  0.600000
3      D    26.0  0.600000
4      D    26.0  0.600000
5      D    26.0  0.600000

下面是一个使用重塑的方法:

(df
.assign(idx=df.groupby('Column1').cumcount())
.pivot('idx', 'Column1')
.pipe(lambda d: d.fillna(d.mean()))
.stack()
.reset_index('Column1')
.sort_values(by='Column1')
)

输出:

Column1  Column2    Column3
idx                         
0        A    24.0  0.200000
1        A    25.0  0.300000
2        A    21.0  0.400000
3        A    33.0  0.500000
0        B    26.0  0.600000
1        B    24.0  0.200000
2        B    25.0  0.300000
3        B    25.0  0.366667
0        C    21.0  0.400000
1        C    33.0  0.500000
2        C    27.0  0.450000
3        C    27.0  0.450000
0        D    26.0  0.600000
1        D    26.0  0.600000
2        D    26.0  0.600000
3        D    26.0  0.600000

我想这就是你要找的。

df = pd.DataFrame({"Column1":
["A", "A", "A", "A", "B", "B", "B", "C", "C", "D"],
"Column2": [24., 25, 21., 33, 26, 24., 25, 21., 33, 26],
"Column3": [0.2, 0.3, 0.4, 0.5, 0.6, 0.2, 0.3, 0.4, 0.5, 0.6]})
# get max value 
max_val = df.groupby('Column1').size().max()
# get mean for each group(A, B, C, D)
mean_df = df.groupby('Column1').mean().reset_index()
new_df = []
for col, grp in df.groupby('Column1'):
append_list = [grp]
if(len(grp) < max_val):
for i in range(max_val - len(grp)):
append_list.append(mean_df[mean_df['Column1'] == col])
new_df.append(pd.concat(append_list))
output_df = pd.concat(new_df)
output_df

相关内容

最新更新