首页 > 解决方案 > 使用 Pandas,如何根据给定条件的前几行的平均值将公式应用于多行?

问题描述

好吧,复杂的标题。这是我要完成的工作:

假设我有一个 n 行的数据框,其中填充了来自一台实验室设备的数据。每隔一段时间,那台设备就会自我校准,并且列中会出现几TrueCalibrating。校准时,CalConstant列为零,未校准的数据保存到Data列中。一旦它完成了这个过程,它就会对 进行平均Data并将其存储在CalConstant列中。在正常运行期间,Data是系统测量值减去电流的结果CalConstant

原来这台设备计算的自校准常数有误,我需要手动重新做。这将通过在每次仪器自校准时对标志Data所在的列进行平均来实现。该平均值将存储在列中,并将在每一行中保留,直到下一次自校准。然后它将取下一个自校准数据的平均值,并将其应用于下一个分析数据块,依此类推。CalibratingTrueCalConstant

如果我们要画一幅漫画,它会是这样的。假设我们有这个数据框:

Index   Data  Calibrating  CalConstant
0      49.91         True          0.0
1      49.06         True          0.0
2      50.38         True          0.0
3      47.82         True          0.0
4      51.58         True          0.0
5      11.63        False        39.75
6      10.42        False        39.75
7      11.67        False        39.75
8      10.12        False        39.75
9      10.67        False        39.75
10     10.89        False        39.75
11     11.23        False        39.75
12     10.43        False        39.75
13     11.26        False        39.75
14     10.64        False        39.75
15     50.23         True          0.0
16     52.63         True          0.0
17     49.32         True          0.0
18     50.99         True          0.0
19     51.34         True          0.0
20     12.37        False        40.90
21     11.47        False        40.90
22     10.81        False        40.90
23     13.27        False        40.90
24     12.73        False        40.90
25     11.31        False        40.90
26     12.85        False        40.90
27     10.42        False        40.90
28     11.25        False        40.90
29     10.54        False        40.90

此处,第 0-4 行是仪器校准时。但是,它错误地计算了背景!它应该是 49.75,因此对于第 5-14 行,数据报告不正确。第 15-19 行的校准问题重复出现,第 20-29 行的数据不正确。在这种情况下,CalConstant10 是关闭的,但实际上,这些值遍布整个地图并且不容易修复。这只是一部卡通片。这就是为什么我需要弄清楚如何应用数学,而不仅仅是摆弄值。

那么现在:在我的数据中,后台校准不会定期发生,但它总是具有相同数量的条目。我需要

  1. 从列中找出正确的背景Datawhile Calibratingis True,
  2. Data先把不正确的加回CalConstant,再减去正确的,找出正确的。

第 2 步很简单,因为我可以添加一个新列,CorrectCalConstant而且它是一个易于应用的公式。困难的部分是弄清楚如何遍历数据帧并找到校准块的开始位置,抓取该块,并仅将其应用到下一个校准块。

我的实际输出可能如下所示:

Index   Data  Calibrating  CalConstant  ActualCalConstant  ActualData
0      49.91         True          0.0                0.0       49.91
1      49.06         True          0.0                0.0       49.06
2      50.38         True          0.0                0.0       50.38
3      47.82         True          0.0                0.0       47.82
4      51.58         True          0.0                0.0       51.58
5      11.63        False        39.75              49.75        1.63
6      10.42        False        39.75              49.75        0.42
7      11.67        False        39.75              49.75        1.67
8      10.12        False        39.75              49.75        0.12
9      10.67        False        39.75              49.75        0.67
10     10.89        False        39.75              49.75        0.89
11     11.23        False        39.75              49.75        1.23
12     10.43        False        39.75              49.75        0.43
13     11.26        False        39.75              49.75        1.26
14     10.64        False        39.75              49.75        0.64
15     50.23         True          0.0                0.0       50.23
16     52.63         True          0.0                0.0       52.63
17     49.32         True          0.0                0.0       49.32
18     50.99         True          0.0                0.0       50.99
19     51.34         True          0.0                0.0       51.34
20     12.37        False        40.90              50.90        2.37
21     11.47        False        40.90              50.90        1.47
22     10.81        False        40.90              50.90        0.81
23     13.27        False        40.90              50.90        3.27
24     12.73        False        40.90              50.90        2.73
25     11.31        False        40.90              50.90        1.31
26     12.85        False        40.90              50.90        2.85
27     10.42        False        40.90              50.90        0.42
28     11.25        False        40.90              50.90        1.25
29     10.54        False        40.90              50.90        0.54

标签: pythonpandas

解决方案


numpy.where与先前组的ActualCalConstant列计数一起使用,因此这里是 的平均值:mean049.750rows 0-4

m = df['Calibrating']
s = df.groupby((~m).cumsum()[m])['Data'].transform('mean').ffill()
df['ActualCalConstant'] = np.where(df['Calibrating'], 0, s)

s1 = df['ActualCalConstant'].sub(df['CalConstant'])
df['ActualData'] = np.where(df['Calibrating'], df['Data'], df['Data'].sub(s1))

print (df)
    Index   Data  Calibrating  CalConstant  ActualCalConstant  ActualData
0       0  49.91         True         0.00              0.000      49.910
1       1  49.06         True         0.00              0.000      49.060
2       2  50.38         True         0.00              0.000      50.380
3       3  47.82         True         0.00              0.000      47.820
4       4  51.58         True         0.00              0.000      51.580
5       5  11.63        False        39.75             49.750       1.630
6       6  10.42        False        39.75             49.750       0.420
7       7  11.67        False        39.75             49.750       1.670
8       8  10.12        False        39.75             49.750       0.120
9       9  10.67        False        39.75             49.750       0.670
10     10  10.89        False        39.75             49.750       0.890
11     11  11.23        False        39.75             49.750       1.230
12     12  10.43        False        39.75             49.750       0.430
13     13  11.26        False        39.75             49.750       1.260
14     14  10.64        False        39.75             49.750       0.640
15     15  50.23         True         0.00              0.000      50.230
16     16  52.63         True         0.00              0.000      52.630
17     17  49.32         True         0.00              0.000      49.320
18     18  50.99         True         0.00              0.000      50.990
19     19  51.34         True         0.00              0.000      51.340
20     20  12.37        False        40.90             50.902       2.368
21     21  11.47        False        40.90             50.902       1.468
22     22  10.81        False        40.90             50.902       0.808
23     23  13.27        False        40.90             50.902       3.268
24     24  12.73        False        40.90             50.902       2.728
25     25  11.31        False        40.90             50.902       1.308
26     26  12.85        False        40.90             50.902       2.848
27     27  10.42        False        40.90             50.902       0.418
28     28  11.25        False        40.90             50.902       1.248
29     29  10.54        False        40.90             50.902       0.538

说明

0首先是按累计总和仅为组创建唯一组Series.cumsum

m = df['Calibrating']
print ((~m).cumsum()[m])
0      0
1      0
2      0
3      0
4      0
15    10
16    10
17    10
18    10
19    10
Name: Calibrating, dtype: int32

然后用于GroupBy.transform每组重复mean

print (df.groupby((~m).cumsum()[m])['Data'].transform('mean'))
0     49.750
1     49.750
2     49.750
3     49.750
4     49.750
5        NaN
6        NaN
7        NaN
8        NaN
9        NaN
10       NaN
11       NaN
12       NaN
13       NaN
14       NaN
15    50.902
16    50.902
17    50.902
18    50.902
19    50.902
20       NaN
21       NaN
22       NaN
23       NaN
24       NaN
25       NaN
26       NaN
27       NaN
28       NaN
29       NaN
Name: Data, dtype: float64

最后添加前向填充缺失值:

print (df.groupby((~m).cumsum()[m])['Data'].transform('mean').ffill())
0     49.750
1     49.750
2     49.750
3     49.750
4     49.750
5     49.750
6     49.750
7     49.750
8     49.750
9     49.750
10    49.750
11    49.750
12    49.750
13    49.750
14    49.750
15    50.902
16    50.902
17    50.902
18    50.902
19    50.902
20    50.902
21    50.902
22    50.902
23    50.902
24    50.902
25    50.902
26    50.902
27    50.902
28    50.902
29    50.902
Name: Data, dtype: float64

推荐阅读