Pandas数据框:当列总和超过阈值时,按比例缩小值

时间:2019-08-25 22:20:10

标签: python pandas dataframe

初始情况

请考虑以下示例数据框:

/acc/

打印形式如下:

df = pd.DataFrame({
    'A': [3., 2., 1., np.nan],
    'B': [7., np.nan, 1., 3.],
    'C': [4., 5., 1., 2.],
    'D': [1., 0., 2., 3.]    
})

所需结果

我现在想对此数据框的每一列执行以下操作:

  1. 计算列值的总和(忽略任何NaN值)。
  2. 如果总和超过10.0,那么我想统一缩小列中的所有值,以使新总和恰好是10.0(再次忽略任何NaN值)。

基本上,我想获得一个看起来像这样的结果数据框:

     A    B    C    D
0  3.0  7.0  4.0  1.0
1  2.0  NaN  5.0  0.0
2  1.0  1.0  1.0  2.0
3  NaN  3.0  2.0  3.0

到目前为止已尝试

下面的代码获得所需的结果。

     A         B         C    D
0  3.0  6.363636  3.333333  1.0
1  2.0       NaN  4.166667  0.0
2  1.0  0.909091  0.833333  2.0
3  NaN  2.727273  1.666667  3.0

但是对于我来说,这段代码有点冗长和效率低下。根据到目前为止我对大熊猫的经验,我怀疑仍然可以使用更加矢量化的解决方案。谁能帮助我找到这个?

2 个答案:

答案 0 :(得分:4)

这是一种方法:

thres = 10
result = df * thres / df.sum().clip(lower=thres)

答案 1 :(得分:1)

这是另一种方法:

colSums = df.sum()
df / ((colSums * (colSums > 10) / 10) + (colSums <= 10))

在这里,我们为每个列创建一个具有求和值的变量,然后分母检查列的总和是否超过10,以调整这些列,使其总和为10。那些总和小于10的列将增加到1,这样我们就不会除以0。然后将所得数组在各列之间进行划分。这将返回期望的结果。

Out[46]: 
     A         B         C    D
0  3.0  6.363636  3.333333  1.0
1  2.0       NaN  4.166667  0.0
2  1.0  0.909091  0.833333  2.0
3  NaN  2.727273  1.666667  3.0