pandas 中平均值的复杂计算

a complex computing of the average value in pandas

这是我在这个论坛上的第一个问题。

我正在进行实验,测量应用不同实验条件的设备的电流-电压曲线。

不同的实验条件编码成一个参数K

我正在使用 前后 电压扫描对电流 I 进行测量,V 从 O 到 2V,然后从 2V 到 -2V然后回到 0V。

K 的每个值进行多次测量,以获得每个电压点(反向和正向值)的电流平均值。每个测量值都归因于一个名为 iter 的参数(例如从 0 到 3)。

我已将所有数据收集到 pandas 数据帧 df 中,我将代码放在下面,该代码能够生成典型的 df 我拥有的(真实的太大了):

import numpy as np
import pandas as pd

K_col=[]
iter_col=[]
V_col=[]
I_col=[]
niter = 3
V_val = [0,1,2,1,0,-1,-2,-1,0]
K_val = [1,2]
for K in K_val:
    for it in range(niter):
        for V in V_val:
            K_col.append(K)
            iter_col.append(it+1)
            V_col.append(V)
            I_col.append((2*K+np.random.random())*V)
d={'K':K_col,'iter':iter_col,'V':V_col,'I':I_col}
df=pd.DataFrame(d)

我想计算每个电压下 I 的平均值,并比较实验条件 K 的影响。

例如,让我们看一下针对 K=1 进行的 2 次测量:

df[(df.K==1)&(df.iter.isin([1,2]))]

输出:


    K iter  V      I
0   1   1   0   0.000000
1   1   1   1   2.513330
2   1   1   2   4.778719
3   1   1   1   2.430393
4   1   1   0   0.000000
5   1   1   -1  -2.705487
6   1   1   -2  -4.235055
7   1   1   -1  -2.278295
8   1   1   0   0.000000
9   1   2   0   0.000000
10  1   2   1   2.535058
11  1   2   2   4.529292
12  1   2   1   2.426209
13  1   2   0   0.000000
14  1   2   -1  -2.878359
15  1   2   -2  -4.061515
16  1   2   -1  -2.294630
17  1   2   0   0.000000

我们可以看到,对于实验 1 (iter=1),V 在 0 处多次出现(索引 0、4 和 8)。我不想丢失这些不同的数据点。

I_avg 的第一个数据点应该是 (I[0]+I[9])/2,这对应于 0V 的第一个测量值。第二个数据点应该是 (I[1]+I[10])/2,它对应于在 1V 下测量的 avg_I 随着 V 值的增加等......直到 (I[8]+I[17])/2 这将是我在 0V 的最后一个数据点。

我的第一个想法是使用 groupby() 方法,使用 KV 作为键,但这行不通,因为 V 因此来回变化对于每个测量值,我们都有 V 的重复值,而 groupby 只会关注 V.

的唯一值

我想要的最终数据框应该如下所示:

    K   V   avg_I
0   1   0   0.000000
1   1   1   2.513330
2   1   2   4.778719
3   1   1   2.430393
4   1   0   0.000000
5   1   -1  -2.705487
6   1   -2  -4.235055
7   1   1   -2.278295
8   1   0   0.000000
9   1   0   0.000000
10  2   1   2.513330
11  2   2   4.778719
12  2   1   2.430393
13  2   0   0.000000
14  2   -1  -2.705487
15  2   -2  -4.235055
16  2   1   -2.278295
17  2   0   0.000000

有人知道怎么做吗?

如果我没有理解错的话,你想要一个新的数据点来表示每个 V 类别的平均 I。我们可以通过获取每个 V 的 I 的平均值然后将其映射到完整数据帧来实现这一点。

avg_I = df.groupby(['V'], as_index=False).mean()[['V', 'I']]
df['avg_I'] = df.apply(lambda x: float(avg_I['I'][avg_I['V'] == x['V']]), axis=1)
df.head()

输出:

    K   iter    V   I       avg_I
0   1   1       0   0.00    0.00
1   1   1       1   2.34    3.55
2   1   1       2   4.54    6.89
3   1   1       1   2.02    3.55
4   1   1       0   0.00    0.00
df.plot()

为了计算均值并同时考虑迭代期间每个观察值的位置,您可以添加一个包含此信息的额外列,如下所示:

len_iter = 9
num_iter = len(df['iter'].unique())
num_K = len(df['K'].unique())

df['index'] = np.tile(np.arange(len_iter), num_iter*num_K)

然后计算分组依据和均值以获得所需的结果:

df.groupby(['K', 'V', 'index'])['I'].mean().reset_index().drop(['index'], axis=1)
    K    V          I
0   1   -2  -5.070126
1   1   -1  -2.598104
2   1   -1  -2.576927
3   1    0   0.000000
4   1    0   0.000000
5   1    0   0.000000
6   1    1   2.232128
7   1    1   2.359398
8   1    2   4.824657
9   2   -2  -9.031487
10  2   -1  -4.125880
11  2   -1  -4.350776
12  2    0   0.000000
13  2    0   0.000000
14  2    0   0.000000
15  2    1   4.535478
16  2    1   4.492122
17  2    2   8.569701