Pandas DataFrame中每行排除一个值的平均函数

3

有没有一种简单的方法来计算pandas DataFrame中每列的平均值,并且对于每行排除特定值?下面每行中的x标记了要从计算中排除的值:

    a    b                     a    b                    a    b
0   1    2                 0   x    x                0   1    2
1   2    4    first loop   1   2    4   second loop  1   x    x   etc.
2   3    6       --->      2   3    6     --->       2   3    6   --->
3   4    8                 3   4    8                3   4    8
4   5   10                 4   5   10                4   5   10
                           ____________              _____________
                   col_avg:  3.5  7.0        col_avg: 3.25  6.5

Using only 4 values at each iteration, as the "x" is excluded from data set

导致一个新的DataFrame。
    a_x    b_x
0   3.5    7.0
1   3.25   6.5
2   3.0    6.0
3   2.75   5.5
4   2.5    5.0

感谢 /N
3个回答

4
为了开始第一步,假设我们对求和而不是计算平均值感兴趣。在这种情况下,我们将沿每列添加除当前元素外的所有元素。另一种解决方法是沿着每列求和所有元素并减去当前元素本身。因此,我们可以使用df.sum(0)获取所有列的总和,然后简单地从中减去df,保持轴对齐。使用Broadcasting可以一次性处理所有列的操作。
为了获得第二步的平均值,我们只需将每列的求和除以涉及的元素数量,即df.shape[0]-1
因此,我们将拥有一个向量化的解决方案,如下所示-
df_out = (df.sum(0) - df)/float(df.shape[0]-1)

样例运行 -

In [128]: df
Out[128]: 
   a   b
0  1   2
1  2   4
2  3   6
3  4   8
4  5  10

In [129]: (df.sum(0) - df)/float(df.shape[0]-1)
Out[129]: 
      a    b
0  3.50  7.0
1  3.25  6.5
2  3.00  6.0
3  2.75  5.5
4  2.50  5.0

要将列名设置为期望的名称,请执行:df_out.columns = ['a_x','b_x']


谢谢,完美运作!由于数据包含NaN值,因此需要使用df.count()来计算“真实”平均值,而不是使用df_shape[0],否则我会将NaN视为实际值进行计数。然而,我在问题中没有指定这一点,只是提供给你参考。 - gussilago

0

我遇到了类似的问题,但需要计算平均值和标准差,不包括当前行

由于需要所有值和组的平均值,标准差的计算要困难得多

以下内容可以轻松扩展到 numpy 的任何聚合函数

In [266]: df = pd.DataFrame({"a": np.arange(5) + 1, "b": 2 * (np.arange(5) + 1)})

In [267]: df
Out[267]:
   a   b
0  1   2
1  2   4
2  3   6
3  4   8
4  5  10

In [268]: import numpy.ma as ma
     ...: import numpy as np

通过将DataFrame的值堆叠为与行数相同的行来创建一个三维numpy数组。
In [269]: t = np.stack(tuple(df.values for _ in range(len(df.index))), axis=0)

In [270]: t
Out[270]:
array([[[ 1,  2],
        [ 2,  4],
        [ 3,  6],
        [ 4,  8],
        [ 5, 10]],

       [[ 1,  2],
        [ 2,  4],
        [ 3,  6],
        [ 4,  8],
        [ 5, 10]],

       [[ 1,  2],
        [ 2,  4],
        [ 3,  6],
        [ 4,  8],
        [ 5, 10]],

       [[ 1,  2],
        [ 2,  4],
        [ 3,  6],
        [ 4,  8],
        [ 5, 10]],

       [[ 1,  2],
        [ 2,  4],
        [ 3,  6],
        [ 4,  8],
        [ 5, 10]]])

创建一组堆叠的单位矩阵,用作聚合函数中的掩码(即排除当前行)。
In [271]: e = np.stack(tuple(np.eye(len(df.index)) for _ in range(len(df.columns))), axis=2)

In [272]: e
Out[272]:
array([[[1., 1.],
        [0., 0.],
        [0., 0.],
        [0., 0.],
        [0., 0.]],

       [[0., 0.],
        [1., 1.],
        [0., 0.],
        [0., 0.],
        [0., 0.]],

       [[0., 0.],
        [0., 0.],
        [1., 1.],
        [0., 0.],
        [0., 0.]],

       [[0., 0.],
        [0., 0.],
        [0., 0.],
        [1., 1.],
        [0., 0.]],

       [[0., 0.],
        [0., 0.],
        [0., 0.],
        [0., 0.],
        [1., 1.]]])

从堆叠的数据和标识构建一个掩码数组(numpy.ma.array)。
In [275]: masked_array = ma.array(t, mask=e)

In [276]: masked_array
Out[276]:
masked_array(
  data=[[[--, --],
         [2, 4],
         [3, 6],
         [4, 8],
         [5, 10]],

        [[1, 2],
         [--, --],
         [3, 6],
         [4, 8],
         [5, 10]],

        [[1, 2],
         [2, 4],
         [--, --],
         [4, 8],
         [5, 10]],

        [[1, 2],
         [2, 4],
         [3, 6],
         [--, --],
         [5, 10]],

        [[1, 2],
         [2, 4],
         [3, 6],
         [4, 8],
         [--, --]]],
  mask=[[[ True,  True],
         [False, False],
         [False, False],
         [False, False],
         [False, False]],

        [[False, False],
         [ True,  True],
         [False, False],
         [False, False],
         [False, False]],

        [[False, False],
         [False, False],
         [ True,  True],
         [False, False],
         [False, False]],

        [[False, False],
         [False, False],
         [False, False],
         [ True,  True],
         [False, False]],

        [[False, False],
         [False, False],
         [False, False],
         [False, False],
         [ True,  True]]],
  fill_value=999999)

最后计算您的聚合值

In [277]: np.nanmean(masked_array, axis=1).data
Out[277]:
array([[3.5 , 7.  ],
       [3.25, 6.5 ],
       [3.  , 6.  ],
       [2.75, 5.5 ],
       [2.5 , 5.  ]])

In [278]: np.nanstd(masked_array, axis=1).data
Out[278]:
array([[1.11803399, 2.23606798],
       [1.47901995, 2.95803989],
       [1.58113883, 3.16227766],
       [1.47901995, 2.95803989],
       [1.11803399, 2.23606798]])

0

以下是使用 pd.concat()drop() 的方法

pd.concat([df.drop(r).mean() for r in df.index],keys=df.index).unstack()

或者

pd.concat([df.drop(r).mean() for r in df.index],axis=1).T

或者

df.apply(lambda x: [np.roll(x,-i)[1:].mean() for i in range(df.shape[0])])

输出:

      a    b
0  3.50  7.0
1  3.25  6.5
2  3.00  6.0
3  2.75  5.5
4  2.50  5.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接